1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * I2C link layer for the NXP NCI driver
4 *
5 * Copyright (C) 2014 NXP Semiconductors All rights reserved.
6 * Copyright (C) 2012-2015 Intel Corporation. All rights reserved.
7 *
8 * Authors: Clément Perrochaud <clement.perrochaud@nxp.com>
9 * Authors: Oleg Zhurakivskyy <oleg.zhurakivskyy@intel.com>
10 *
11 * Derived from PN544 device driver:
12 * Copyright (C) 2012 Intel Corporation. All rights reserved.
13 */
14
15 #include <linux/acpi.h>
16 #include <linux/delay.h>
17 #include <linux/i2c.h>
18 #include <linux/interrupt.h>
19 #include <linux/irq.h>
20 #include <linux/module.h>
21 #include <linux/nfc.h>
22 #include <linux/gpio/consumer.h>
23 #include <linux/unaligned.h>
24
25 #include <net/nfc/nfc.h>
26
27 #include "nxp-nci.h"
28
29 #define NXP_NCI_I2C_DRIVER_NAME "nxp-nci_i2c"
30
31 #define NXP_NCI_I2C_MAX_PAYLOAD 32
32
33 struct nxp_nci_i2c_phy {
34 struct i2c_client *i2c_dev;
35 struct nci_dev *ndev;
36
37 struct gpio_desc *gpiod_en;
38 struct gpio_desc *gpiod_fw;
39
40 int hard_fault; /*
41 * < 0 if hardware error occurred (e.g. i2c err)
42 * and prevents normal operation.
43 */
44 };
45
nxp_nci_i2c_set_mode(void * phy_id,enum nxp_nci_mode mode)46 static int nxp_nci_i2c_set_mode(void *phy_id,
47 enum nxp_nci_mode mode)
48 {
49 struct nxp_nci_i2c_phy *phy = (struct nxp_nci_i2c_phy *) phy_id;
50
51 gpiod_set_value_cansleep(phy->gpiod_fw, (mode == NXP_NCI_MODE_FW) ? 1 : 0);
52 gpiod_set_value_cansleep(phy->gpiod_en, (mode != NXP_NCI_MODE_COLD) ? 1 : 0);
53 usleep_range(10000, 15000);
54
55 if (mode == NXP_NCI_MODE_COLD)
56 phy->hard_fault = 0;
57
58 return 0;
59 }
60
nxp_nci_i2c_write(void * phy_id,struct sk_buff * skb)61 static int nxp_nci_i2c_write(void *phy_id, struct sk_buff *skb)
62 {
63 int r;
64 struct nxp_nci_i2c_phy *phy = phy_id;
65 struct i2c_client *client = phy->i2c_dev;
66
67 if (phy->hard_fault != 0)
68 return phy->hard_fault;
69
70 r = i2c_master_send(client, skb->data, skb->len);
71 if (r < 0) {
72 /* Retry, chip was in standby */
73 msleep(110);
74 r = i2c_master_send(client, skb->data, skb->len);
75 }
76
77 if (r < 0) {
78 nfc_err(&client->dev, "Error %d on I2C send\n", r);
79 } else if (r != skb->len) {
80 nfc_err(&client->dev,
81 "Invalid length sent: %u (expected %u)\n",
82 r, skb->len);
83 r = -EREMOTEIO;
84 } else {
85 /* Success but return 0 and not number of bytes */
86 r = 0;
87 }
88
89 return r;
90 }
91
92 static const struct nxp_nci_phy_ops i2c_phy_ops = {
93 .set_mode = nxp_nci_i2c_set_mode,
94 .write = nxp_nci_i2c_write,
95 };
96
nxp_nci_i2c_fw_read(struct nxp_nci_i2c_phy * phy,struct sk_buff ** skb)97 static int nxp_nci_i2c_fw_read(struct nxp_nci_i2c_phy *phy,
98 struct sk_buff **skb)
99 {
100 struct i2c_client *client = phy->i2c_dev;
101 size_t frame_len;
102 __be16 header;
103 int r;
104
105 r = i2c_master_recv(client, (u8 *) &header, NXP_NCI_FW_HDR_LEN);
106 if (r < 0) {
107 goto fw_read_exit;
108 } else if (r != NXP_NCI_FW_HDR_LEN) {
109 nfc_err(&client->dev, "Incorrect header length: %u\n", r);
110 r = -EBADMSG;
111 goto fw_read_exit;
112 }
113
114 frame_len = (be16_to_cpu(header) & NXP_NCI_FW_FRAME_LEN_MASK) +
115 NXP_NCI_FW_CRC_LEN;
116
117 *skb = alloc_skb(NXP_NCI_FW_HDR_LEN + frame_len, GFP_KERNEL);
118 if (*skb == NULL) {
119 r = -ENOMEM;
120 goto fw_read_exit;
121 }
122
123 skb_put_data(*skb, &header, NXP_NCI_FW_HDR_LEN);
124
125 r = i2c_master_recv(client, skb_put(*skb, frame_len), frame_len);
126 if (r < 0) {
127 goto fw_read_exit_free_skb;
128 } else if (r != frame_len) {
129 nfc_err(&client->dev,
130 "Invalid frame length: %u (expected %zu)\n",
131 r, frame_len);
132 r = -EBADMSG;
133 goto fw_read_exit_free_skb;
134 }
135
136 return 0;
137
138 fw_read_exit_free_skb:
139 kfree_skb(*skb);
140 fw_read_exit:
141 return r;
142 }
143
nxp_nci_i2c_nci_read(struct nxp_nci_i2c_phy * phy,struct sk_buff ** skb)144 static int nxp_nci_i2c_nci_read(struct nxp_nci_i2c_phy *phy,
145 struct sk_buff **skb)
146 {
147 struct nci_ctrl_hdr header; /* May actually be a data header */
148 struct i2c_client *client = phy->i2c_dev;
149 int r;
150
151 r = i2c_master_recv(client, (u8 *) &header, NCI_CTRL_HDR_SIZE);
152 if (r < 0) {
153 goto nci_read_exit;
154 } else if (r != NCI_CTRL_HDR_SIZE) {
155 nfc_err(&client->dev, "Incorrect header length: %u\n", r);
156 r = -EBADMSG;
157 goto nci_read_exit;
158 }
159
160 *skb = alloc_skb(NCI_CTRL_HDR_SIZE + header.plen, GFP_KERNEL);
161 if (*skb == NULL) {
162 r = -ENOMEM;
163 goto nci_read_exit;
164 }
165
166 skb_put_data(*skb, (void *)&header, NCI_CTRL_HDR_SIZE);
167
168 if (!header.plen)
169 return 0;
170
171 r = i2c_master_recv(client, skb_put(*skb, header.plen), header.plen);
172 if (r < 0) {
173 goto nci_read_exit_free_skb;
174 } else if (r != header.plen) {
175 nfc_err(&client->dev,
176 "Invalid frame payload length: %u (expected %u)\n",
177 r, header.plen);
178 r = -EBADMSG;
179 goto nci_read_exit_free_skb;
180 }
181
182 return 0;
183
184 nci_read_exit_free_skb:
185 kfree_skb(*skb);
186 nci_read_exit:
187 return r;
188 }
189
nxp_nci_i2c_irq_thread_fn(int irq,void * phy_id)190 static irqreturn_t nxp_nci_i2c_irq_thread_fn(int irq, void *phy_id)
191 {
192 struct nxp_nci_i2c_phy *phy = phy_id;
193 struct i2c_client *client;
194 struct nxp_nci_info *info;
195
196 struct sk_buff *skb = NULL;
197 int r = 0;
198
199 if (!phy || !phy->ndev)
200 goto exit_irq_none;
201
202 client = phy->i2c_dev;
203
204 if (!client || irq != client->irq)
205 goto exit_irq_none;
206
207 info = nci_get_drvdata(phy->ndev);
208
209 if (!info)
210 goto exit_irq_none;
211
212 mutex_lock(&info->info_lock);
213
214 if (phy->hard_fault != 0)
215 goto exit_irq_handled;
216
217 switch (info->mode) {
218 case NXP_NCI_MODE_NCI:
219 r = nxp_nci_i2c_nci_read(phy, &skb);
220 break;
221 case NXP_NCI_MODE_FW:
222 r = nxp_nci_i2c_fw_read(phy, &skb);
223 break;
224 case NXP_NCI_MODE_COLD:
225 r = -EREMOTEIO;
226 break;
227 }
228
229 if (r == -EREMOTEIO) {
230 phy->hard_fault = r;
231 if (info->mode == NXP_NCI_MODE_FW)
232 nxp_nci_fw_recv_frame(phy->ndev, NULL);
233 }
234 if (r < 0) {
235 nfc_err(&client->dev, "Read failed with error %d\n", r);
236 goto exit_irq_handled;
237 }
238
239 switch (info->mode) {
240 case NXP_NCI_MODE_NCI:
241 nci_recv_frame(phy->ndev, skb);
242 break;
243 case NXP_NCI_MODE_FW:
244 nxp_nci_fw_recv_frame(phy->ndev, skb);
245 break;
246 case NXP_NCI_MODE_COLD:
247 break;
248 }
249
250 exit_irq_handled:
251 mutex_unlock(&info->info_lock);
252 return IRQ_HANDLED;
253 exit_irq_none:
254 WARN_ON_ONCE(1);
255 return IRQ_NONE;
256 }
257
258 static const struct acpi_gpio_params firmware_gpios = { 1, 0, false };
259 static const struct acpi_gpio_params enable_gpios = { 2, 0, false };
260
261 static const struct acpi_gpio_mapping acpi_nxp_nci_gpios[] = {
262 { "enable-gpios", &enable_gpios, 1 },
263 { "firmware-gpios", &firmware_gpios, 1 },
264 { }
265 };
266
nxp_nci_i2c_probe(struct i2c_client * client)267 static int nxp_nci_i2c_probe(struct i2c_client *client)
268 {
269 struct device *dev = &client->dev;
270 struct nxp_nci_i2c_phy *phy;
271 unsigned long irqflags;
272 int r;
273
274 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
275 nfc_err(&client->dev, "Need I2C_FUNC_I2C\n");
276 return -ENODEV;
277 }
278
279 phy = devm_kzalloc(&client->dev, sizeof(struct nxp_nci_i2c_phy),
280 GFP_KERNEL);
281 if (!phy)
282 return -ENOMEM;
283
284 phy->i2c_dev = client;
285 i2c_set_clientdata(client, phy);
286
287 r = devm_acpi_dev_add_driver_gpios(dev, acpi_nxp_nci_gpios);
288 if (r)
289 dev_dbg(dev, "Unable to add GPIO mapping table\n");
290
291 phy->gpiod_en = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
292 if (IS_ERR(phy->gpiod_en)) {
293 nfc_err(dev, "Failed to get EN gpio\n");
294 return PTR_ERR(phy->gpiod_en);
295 }
296
297 phy->gpiod_fw = devm_gpiod_get_optional(dev, "firmware", GPIOD_OUT_LOW);
298 if (IS_ERR(phy->gpiod_fw)) {
299 nfc_err(dev, "Failed to get FW gpio\n");
300 return PTR_ERR(phy->gpiod_fw);
301 }
302
303 r = nxp_nci_probe(phy, &client->dev, &i2c_phy_ops,
304 NXP_NCI_I2C_MAX_PAYLOAD, &phy->ndev);
305 if (r < 0)
306 return r;
307
308 /*
309 * ACPI platforms may report incorrect IRQ trigger types
310 * (e.g. level-high), which can lead to interrupt storms.
311 *
312 * Use the historically stable rising-edge trigger for ACPI devices.
313 *
314 * On non-ACPI systems (e.g. Device Tree), prefer the firmware-
315 * provided trigger type, falling back to rising-edge if not set.
316 */
317 if (ACPI_COMPANION(dev)) {
318 irqflags = IRQF_TRIGGER_RISING;
319 } else {
320 irqflags = irq_get_trigger_type(client->irq);
321 if (!irqflags)
322 irqflags = IRQF_TRIGGER_RISING;
323 }
324
325 r = request_threaded_irq(client->irq, NULL,
326 nxp_nci_i2c_irq_thread_fn,
327 irqflags | IRQF_ONESHOT,
328 NXP_NCI_I2C_DRIVER_NAME, phy);
329 if (r < 0)
330 nfc_err(&client->dev, "Unable to register IRQ handler\n");
331
332 return r;
333 }
334
nxp_nci_i2c_remove(struct i2c_client * client)335 static void nxp_nci_i2c_remove(struct i2c_client *client)
336 {
337 struct nxp_nci_i2c_phy *phy = i2c_get_clientdata(client);
338
339 nxp_nci_remove(phy->ndev);
340 free_irq(client->irq, phy);
341 }
342
343 static const struct i2c_device_id nxp_nci_i2c_id_table[] = {
344 { "nxp-nci_i2c" },
345 {}
346 };
347 MODULE_DEVICE_TABLE(i2c, nxp_nci_i2c_id_table);
348
349 static const struct of_device_id of_nxp_nci_i2c_match[] = {
350 { .compatible = "nxp,nxp-nci-i2c", },
351 {}
352 };
353 MODULE_DEVICE_TABLE(of, of_nxp_nci_i2c_match);
354
355 #ifdef CONFIG_ACPI
356 static const struct acpi_device_id acpi_id[] = {
357 { "NXP1001" },
358 { "NXP1002" },
359 { "NXP7471" },
360 { }
361 };
362 MODULE_DEVICE_TABLE(acpi, acpi_id);
363 #endif
364
365 static struct i2c_driver nxp_nci_i2c_driver = {
366 .driver = {
367 .name = NXP_NCI_I2C_DRIVER_NAME,
368 .acpi_match_table = ACPI_PTR(acpi_id),
369 .of_match_table = of_nxp_nci_i2c_match,
370 },
371 .probe = nxp_nci_i2c_probe,
372 .id_table = nxp_nci_i2c_id_table,
373 .remove = nxp_nci_i2c_remove,
374 };
375
376 module_i2c_driver(nxp_nci_i2c_driver);
377
378 MODULE_LICENSE("GPL");
379 MODULE_DESCRIPTION("I2C driver for NXP NCI NFC controllers");
380 MODULE_AUTHOR("Clément Perrochaud <clement.perrochaud@nxp.com>");
381 MODULE_AUTHOR("Oleg Zhurakivskyy <oleg.zhurakivskyy@intel.com>");
382