Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16
17#include <linux/acpi.h>
18#include <linux/delay.h>
19#include <linux/i2c.h>
20#include <linux/interrupt.h>
21#include <linux/module.h>
22#include <linux/nfc.h>
23#include <linux/gpio/consumer.h>
24#include <linux/of_gpio.h>
25#include <linux/of_irq.h>
26#include <linux/platform_data/nxp-nci.h>
27#include <asm/unaligned.h>
28
29#include <net/nfc/nfc.h>
30
31#include "nxp-nci.h"
32
33#define NXP_NCI_I2C_DRIVER_NAME "nxp-nci_i2c"
34
35#define NXP_NCI_I2C_MAX_PAYLOAD 32
36
37struct nxp_nci_i2c_phy {
38 struct i2c_client *i2c_dev;
39 struct nci_dev *ndev;
40
41 unsigned int gpio_en;
42 unsigned int gpio_fw;
43
44 int hard_fault; /*
45 * < 0 if hardware error occurred (e.g. i2c err)
46 * and prevents normal operation.
47 */
48};
49
50static int nxp_nci_i2c_set_mode(void *phy_id,
51 enum nxp_nci_mode mode)
52{
53 struct nxp_nci_i2c_phy *phy = (struct nxp_nci_i2c_phy *) phy_id;
54
55 gpio_set_value(phy->gpio_fw, (mode == NXP_NCI_MODE_FW) ? 1 : 0);
56 gpio_set_value(phy->gpio_en, (mode != NXP_NCI_MODE_COLD) ? 1 : 0);
57 usleep_range(10000, 15000);
58
59 if (mode == NXP_NCI_MODE_COLD)
60 phy->hard_fault = 0;
61
62 return 0;
63}
64
65static int nxp_nci_i2c_write(void *phy_id, struct sk_buff *skb)
66{
67 int r;
68 struct nxp_nci_i2c_phy *phy = phy_id;
69 struct i2c_client *client = phy->i2c_dev;
70
71 if (phy->hard_fault != 0)
72 return phy->hard_fault;
73
74 r = i2c_master_send(client, skb->data, skb->len);
75 if (r < 0) {
76 /* Retry, chip was in standby */
77 msleep(110);
78 r = i2c_master_send(client, skb->data, skb->len);
79 }
80
81 if (r < 0) {
82 nfc_err(&client->dev, "Error %d on I2C send\n", r);
83 } else if (r != skb->len) {
84 nfc_err(&client->dev,
85 "Invalid length sent: %u (expected %u)\n",
86 r, skb->len);
87 r = -EREMOTEIO;
88 } else {
89 /* Success but return 0 and not number of bytes */
90 r = 0;
91 }
92
93 return r;
94}
95
96static const struct nxp_nci_phy_ops i2c_phy_ops = {
97 .set_mode = nxp_nci_i2c_set_mode,
98 .write = nxp_nci_i2c_write,
99};
100
101static int nxp_nci_i2c_fw_read(struct nxp_nci_i2c_phy *phy,
102 struct sk_buff **skb)
103{
104 struct i2c_client *client = phy->i2c_dev;
105 u16 header;
106 size_t frame_len;
107 int r;
108
109 r = i2c_master_recv(client, (u8 *) &header, NXP_NCI_FW_HDR_LEN);
110 if (r < 0) {
111 goto fw_read_exit;
112 } else if (r != NXP_NCI_FW_HDR_LEN) {
113 nfc_err(&client->dev, "Incorrect header length: %u\n", r);
114 r = -EBADMSG;
115 goto fw_read_exit;
116 }
117
118 frame_len = (be16_to_cpu(header) & NXP_NCI_FW_FRAME_LEN_MASK) +
119 NXP_NCI_FW_CRC_LEN;
120
121 *skb = alloc_skb(NXP_NCI_FW_HDR_LEN + frame_len, GFP_KERNEL);
122 if (*skb == NULL) {
123 r = -ENOMEM;
124 goto fw_read_exit;
125 }
126
127 skb_put_data(*skb, &header, NXP_NCI_FW_HDR_LEN);
128
129 r = i2c_master_recv(client, skb_put(*skb, frame_len), frame_len);
130 if (r != frame_len) {
131 nfc_err(&client->dev,
132 "Invalid frame length: %u (expected %zu)\n",
133 r, frame_len);
134 r = -EBADMSG;
135 goto fw_read_exit_free_skb;
136 }
137
138 return 0;
139
140fw_read_exit_free_skb:
141 kfree_skb(*skb);
142fw_read_exit:
143 return r;
144}
145
146static int nxp_nci_i2c_nci_read(struct nxp_nci_i2c_phy *phy,
147 struct sk_buff **skb)
148{
149 struct nci_ctrl_hdr header; /* May actually be a data header */
150 struct i2c_client *client = phy->i2c_dev;
151 int r;
152
153 r = i2c_master_recv(client, (u8 *) &header, NCI_CTRL_HDR_SIZE);
154 if (r < 0) {
155 goto nci_read_exit;
156 } else if (r != NCI_CTRL_HDR_SIZE) {
157 nfc_err(&client->dev, "Incorrect header length: %u\n", r);
158 r = -EBADMSG;
159 goto nci_read_exit;
160 }
161
162 *skb = alloc_skb(NCI_CTRL_HDR_SIZE + header.plen, GFP_KERNEL);
163 if (*skb == NULL) {
164 r = -ENOMEM;
165 goto nci_read_exit;
166 }
167
168 skb_put_data(*skb, (void *)&header, NCI_CTRL_HDR_SIZE);
169
170 r = i2c_master_recv(client, skb_put(*skb, header.plen), header.plen);
171 if (r != header.plen) {
172 nfc_err(&client->dev,
173 "Invalid frame payload length: %u (expected %u)\n",
174 r, header.plen);
175 r = -EBADMSG;
176 goto nci_read_exit_free_skb;
177 }
178
179 return 0;
180
181nci_read_exit_free_skb:
182 kfree_skb(*skb);
183nci_read_exit:
184 return r;
185}
186
187static irqreturn_t nxp_nci_i2c_irq_thread_fn(int irq, void *phy_id)
188{
189 struct nxp_nci_i2c_phy *phy = phy_id;
190 struct i2c_client *client;
191 struct nxp_nci_info *info;
192
193 struct sk_buff *skb = NULL;
194 int r = 0;
195
196 if (!phy || !phy->ndev)
197 goto exit_irq_none;
198
199 client = phy->i2c_dev;
200
201 if (!client || irq != client->irq)
202 goto exit_irq_none;
203
204 info = nci_get_drvdata(phy->ndev);
205
206 if (!info)
207 goto exit_irq_none;
208
209 mutex_lock(&info->info_lock);
210
211 if (phy->hard_fault != 0)
212 goto exit_irq_handled;
213
214 switch (info->mode) {
215 case NXP_NCI_MODE_NCI:
216 r = nxp_nci_i2c_nci_read(phy, &skb);
217 break;
218 case NXP_NCI_MODE_FW:
219 r = nxp_nci_i2c_fw_read(phy, &skb);
220 break;
221 case NXP_NCI_MODE_COLD:
222 r = -EREMOTEIO;
223 break;
224 }
225
226 if (r == -EREMOTEIO) {
227 phy->hard_fault = r;
228 skb = NULL;
229 } else if (r < 0) {
230 nfc_err(&client->dev, "Read failed with error %d\n", r);
231 goto exit_irq_handled;
232 }
233
234 switch (info->mode) {
235 case NXP_NCI_MODE_NCI:
236 nci_recv_frame(phy->ndev, skb);
237 break;
238 case NXP_NCI_MODE_FW:
239 nxp_nci_fw_recv_frame(phy->ndev, skb);
240 break;
241 case NXP_NCI_MODE_COLD:
242 break;
243 }
244
245exit_irq_handled:
246 mutex_unlock(&info->info_lock);
247 return IRQ_HANDLED;
248exit_irq_none:
249 WARN_ON_ONCE(1);
250 return IRQ_NONE;
251}
252
253static int nxp_nci_i2c_parse_devtree(struct i2c_client *client)
254{
255 struct nxp_nci_i2c_phy *phy = i2c_get_clientdata(client);
256 struct device_node *pp;
257 int r;
258
259 pp = client->dev.of_node;
260 if (!pp)
261 return -ENODEV;
262
263 r = of_get_named_gpio(pp, "enable-gpios", 0);
264 if (r == -EPROBE_DEFER)
265 r = of_get_named_gpio(pp, "enable-gpios", 0);
266 if (r < 0) {
267 nfc_err(&client->dev, "Failed to get EN gpio, error: %d\n", r);
268 return r;
269 }
270 phy->gpio_en = r;
271
272 r = of_get_named_gpio(pp, "firmware-gpios", 0);
273 if (r == -EPROBE_DEFER)
274 r = of_get_named_gpio(pp, "firmware-gpios", 0);
275 if (r < 0) {
276 nfc_err(&client->dev, "Failed to get FW gpio, error: %d\n", r);
277 return r;
278 }
279 phy->gpio_fw = r;
280
281 return 0;
282}
283
284static int nxp_nci_i2c_acpi_config(struct nxp_nci_i2c_phy *phy)
285{
286 struct i2c_client *client = phy->i2c_dev;
287 struct gpio_desc *gpiod_en, *gpiod_fw;
288
289 gpiod_en = devm_gpiod_get_index(&client->dev, NULL, 2, GPIOD_OUT_LOW);
290 gpiod_fw = devm_gpiod_get_index(&client->dev, NULL, 1, GPIOD_OUT_LOW);
291
292 if (IS_ERR(gpiod_en) || IS_ERR(gpiod_fw)) {
293 nfc_err(&client->dev, "No GPIOs\n");
294 return -EINVAL;
295 }
296
297 phy->gpio_en = desc_to_gpio(gpiod_en);
298 phy->gpio_fw = desc_to_gpio(gpiod_fw);
299
300 return 0;
301}
302
303static int nxp_nci_i2c_probe(struct i2c_client *client,
304 const struct i2c_device_id *id)
305{
306 struct nxp_nci_i2c_phy *phy;
307 struct nxp_nci_nfc_platform_data *pdata;
308 int r;
309
310 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
311 nfc_err(&client->dev, "Need I2C_FUNC_I2C\n");
312 r = -ENODEV;
313 goto probe_exit;
314 }
315
316 phy = devm_kzalloc(&client->dev, sizeof(struct nxp_nci_i2c_phy),
317 GFP_KERNEL);
318 if (!phy) {
319 r = -ENOMEM;
320 goto probe_exit;
321 }
322
323 phy->i2c_dev = client;
324 i2c_set_clientdata(client, phy);
325
326 pdata = client->dev.platform_data;
327
328 if (!pdata && client->dev.of_node) {
329 r = nxp_nci_i2c_parse_devtree(client);
330 if (r < 0) {
331 nfc_err(&client->dev, "Failed to get DT data\n");
332 goto probe_exit;
333 }
334 } else if (pdata) {
335 phy->gpio_en = pdata->gpio_en;
336 phy->gpio_fw = pdata->gpio_fw;
337 } else if (ACPI_HANDLE(&client->dev)) {
338 r = nxp_nci_i2c_acpi_config(phy);
339 if (r < 0)
340 goto probe_exit;
341 goto nci_probe;
342 } else {
343 nfc_err(&client->dev, "No platform data\n");
344 r = -EINVAL;
345 goto probe_exit;
346 }
347
348 r = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_en,
349 GPIOF_OUT_INIT_LOW, "nxp_nci_en");
350 if (r < 0)
351 goto probe_exit;
352
353 r = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_fw,
354 GPIOF_OUT_INIT_LOW, "nxp_nci_fw");
355 if (r < 0)
356 goto probe_exit;
357
358nci_probe:
359 r = nxp_nci_probe(phy, &client->dev, &i2c_phy_ops,
360 NXP_NCI_I2C_MAX_PAYLOAD, &phy->ndev);
361 if (r < 0)
362 goto probe_exit;
363
364 r = request_threaded_irq(client->irq, NULL,
365 nxp_nci_i2c_irq_thread_fn,
366 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
367 NXP_NCI_I2C_DRIVER_NAME, phy);
368 if (r < 0)
369 nfc_err(&client->dev, "Unable to register IRQ handler\n");
370
371probe_exit:
372 return r;
373}
374
375static int nxp_nci_i2c_remove(struct i2c_client *client)
376{
377 struct nxp_nci_i2c_phy *phy = i2c_get_clientdata(client);
378
379 nxp_nci_remove(phy->ndev);
380 free_irq(client->irq, phy);
381
382 return 0;
383}
384
385static const struct i2c_device_id nxp_nci_i2c_id_table[] = {
386 {"nxp-nci_i2c", 0},
387 {}
388};
389MODULE_DEVICE_TABLE(i2c, nxp_nci_i2c_id_table);
390
391static const struct of_device_id of_nxp_nci_i2c_match[] = {
392 { .compatible = "nxp,nxp-nci-i2c", },
393 {},
394};
395MODULE_DEVICE_TABLE(of, of_nxp_nci_i2c_match);
396
397#ifdef CONFIG_ACPI
398static struct acpi_device_id acpi_id[] = {
399 { "NXP7471" },
400 { },
401};
402MODULE_DEVICE_TABLE(acpi, acpi_id);
403#endif
404
405static struct i2c_driver nxp_nci_i2c_driver = {
406 .driver = {
407 .name = NXP_NCI_I2C_DRIVER_NAME,
408 .acpi_match_table = ACPI_PTR(acpi_id),
409 .of_match_table = of_match_ptr(of_nxp_nci_i2c_match),
410 },
411 .probe = nxp_nci_i2c_probe,
412 .id_table = nxp_nci_i2c_id_table,
413 .remove = nxp_nci_i2c_remove,
414};
415
416module_i2c_driver(nxp_nci_i2c_driver);
417
418MODULE_LICENSE("GPL");
419MODULE_DESCRIPTION("I2C driver for NXP NCI NFC controllers");
420MODULE_AUTHOR("Clément Perrochaud <clement.perrochaud@nxp.com>");
421MODULE_AUTHOR("Oleg Zhurakivskyy <oleg.zhurakivskyy@intel.com>");