Commit | Line | Data |
---|---|---|
46fe7771 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
35630df6 | 2 | /* |
ed06aeef CR |
3 | * I2C Link Layer for ST NCI NFC controller familly based Driver |
4 | * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved. | |
35630df6 CR |
5 | */ |
6 | ||
7 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
8 | ||
35630df6 CR |
9 | #include <linux/module.h> |
10 | #include <linux/i2c.h> | |
ed6a2f3f | 11 | #include <linux/gpio/consumer.h> |
ed6a2f3f | 12 | #include <linux/acpi.h> |
35630df6 CR |
13 | #include <linux/interrupt.h> |
14 | #include <linux/delay.h> | |
15 | #include <linux/nfc.h> | |
a89e68f1 | 16 | #include <linux/of.h> |
35630df6 | 17 | |
e67e7e59 | 18 | #include "st-nci.h" |
35630df6 | 19 | |
30458aac | 20 | #define DRIVER_DESC "NCI NFC driver for ST_NCI" |
35630df6 CR |
21 | |
22 | /* ndlc header */ | |
064d0047 | 23 | #define ST_NCI_FRAME_HEADROOM 1 |
30458aac | 24 | #define ST_NCI_FRAME_TAILROOM 0 |
35630df6 | 25 | |
ed06aeef CR |
26 | #define ST_NCI_I2C_MIN_SIZE 4 /* PCB(1) + NCI Packet header(3) */ |
27 | #define ST_NCI_I2C_MAX_SIZE 250 /* req 4.2.1 */ | |
35630df6 | 28 | |
61a04101 | 29 | #define ST_NCI_DRIVER_NAME "st_nci" |
ed06aeef | 30 | #define ST_NCI_I2C_DRIVER_NAME "st_nci_i2c" |
35630df6 | 31 | |
ed06aeef | 32 | struct st_nci_i2c_phy { |
35630df6 CR |
33 | struct i2c_client *i2c_dev; |
34 | struct llt_ndlc *ndlc; | |
35 | ||
bb2496c3 CR |
36 | bool irq_active; |
37 | ||
a89e68f1 | 38 | struct gpio_desc *gpiod_reset; |
3648dc6d CR |
39 | |
40 | struct st_nci_se_status se_status; | |
35630df6 CR |
41 | }; |
42 | ||
ed06aeef | 43 | static int st_nci_i2c_enable(void *phy_id) |
35630df6 | 44 | { |
ed06aeef | 45 | struct st_nci_i2c_phy *phy = phy_id; |
35630df6 | 46 | |
a89e68f1 | 47 | gpiod_set_value(phy->gpiod_reset, 0); |
35630df6 | 48 | usleep_range(10000, 15000); |
a89e68f1 | 49 | gpiod_set_value(phy->gpiod_reset, 1); |
35630df6 CR |
50 | usleep_range(80000, 85000); |
51 | ||
bb2496c3 | 52 | if (phy->ndlc->powered == 0 && phy->irq_active == 0) { |
05f0939f | 53 | enable_irq(phy->i2c_dev->irq); |
bb2496c3 CR |
54 | phy->irq_active = true; |
55 | } | |
05f0939f | 56 | |
35630df6 CR |
57 | return 0; |
58 | } | |
59 | ||
ed06aeef | 60 | static void st_nci_i2c_disable(void *phy_id) |
35630df6 | 61 | { |
ed06aeef | 62 | struct st_nci_i2c_phy *phy = phy_id; |
35630df6 | 63 | |
05f0939f | 64 | disable_irq_nosync(phy->i2c_dev->irq); |
bb2496c3 | 65 | phy->irq_active = false; |
35630df6 CR |
66 | } |
67 | ||
35630df6 CR |
68 | /* |
69 | * Writing a frame must not return the number of written bytes. | |
70 | * It must return either zero for success, or <0 for error. | |
71 | * In addition, it must not alter the skb | |
72 | */ | |
ed06aeef | 73 | static int st_nci_i2c_write(void *phy_id, struct sk_buff *skb) |
35630df6 | 74 | { |
23ec8eaf | 75 | int r; |
ed06aeef | 76 | struct st_nci_i2c_phy *phy = phy_id; |
35630df6 CR |
77 | struct i2c_client *client = phy->i2c_dev; |
78 | ||
4294e320 CR |
79 | if (phy->ndlc->hard_fault != 0) |
80 | return phy->ndlc->hard_fault; | |
35630df6 CR |
81 | |
82 | r = i2c_master_send(client, skb->data, skb->len); | |
d4a41d10 | 83 | if (r < 0) { /* Retry, chip was in standby */ |
35630df6 CR |
84 | usleep_range(1000, 4000); |
85 | r = i2c_master_send(client, skb->data, skb->len); | |
86 | } | |
87 | ||
88 | if (r >= 0) { | |
89 | if (r != skb->len) | |
90 | r = -EREMOTEIO; | |
91 | else | |
92 | r = 0; | |
93 | } | |
94 | ||
35630df6 CR |
95 | return r; |
96 | } | |
97 | ||
98 | /* | |
99 | * Reads an ndlc frame and returns it in a newly allocated sk_buff. | |
100 | * returns: | |
e7723b33 | 101 | * 0 : if received frame is complete |
35630df6 CR |
102 | * -EREMOTEIO : i2c read error (fatal) |
103 | * -EBADMSG : frame was incorrect and discarded | |
e7723b33 | 104 | * -ENOMEM : cannot allocate skb, frame dropped |
35630df6 | 105 | */ |
ed06aeef | 106 | static int st_nci_i2c_read(struct st_nci_i2c_phy *phy, |
35630df6 CR |
107 | struct sk_buff **skb) |
108 | { | |
109 | int r; | |
110 | u8 len; | |
ed06aeef | 111 | u8 buf[ST_NCI_I2C_MAX_SIZE]; |
35630df6 CR |
112 | struct i2c_client *client = phy->i2c_dev; |
113 | ||
ed06aeef | 114 | r = i2c_master_recv(client, buf, ST_NCI_I2C_MIN_SIZE); |
d4a41d10 | 115 | if (r < 0) { /* Retry, chip was in standby */ |
35630df6 | 116 | usleep_range(1000, 4000); |
ed06aeef | 117 | r = i2c_master_recv(client, buf, ST_NCI_I2C_MIN_SIZE); |
ac633ba6 CR |
118 | } |
119 | ||
ed06aeef | 120 | if (r != ST_NCI_I2C_MIN_SIZE) |
35630df6 | 121 | return -EREMOTEIO; |
35630df6 CR |
122 | |
123 | len = be16_to_cpu(*(__be16 *) (buf + 2)); | |
ed06aeef | 124 | if (len > ST_NCI_I2C_MAX_SIZE) { |
35630df6 CR |
125 | nfc_err(&client->dev, "invalid frame len\n"); |
126 | return -EBADMSG; | |
127 | } | |
128 | ||
ed06aeef | 129 | *skb = alloc_skb(ST_NCI_I2C_MIN_SIZE + len, GFP_KERNEL); |
35630df6 CR |
130 | if (*skb == NULL) |
131 | return -ENOMEM; | |
132 | ||
ed06aeef CR |
133 | skb_reserve(*skb, ST_NCI_I2C_MIN_SIZE); |
134 | skb_put(*skb, ST_NCI_I2C_MIN_SIZE); | |
135 | memcpy((*skb)->data, buf, ST_NCI_I2C_MIN_SIZE); | |
35630df6 CR |
136 | |
137 | if (!len) | |
138 | return 0; | |
139 | ||
140 | r = i2c_master_recv(client, buf, len); | |
141 | if (r != len) { | |
142 | kfree_skb(*skb); | |
143 | return -EREMOTEIO; | |
144 | } | |
145 | ||
146 | skb_put(*skb, len); | |
ed06aeef | 147 | memcpy((*skb)->data + ST_NCI_I2C_MIN_SIZE, buf, len); |
35630df6 | 148 | |
35630df6 CR |
149 | return 0; |
150 | } | |
151 | ||
152 | /* | |
153 | * Reads an ndlc frame from the chip. | |
154 | * | |
30458aac | 155 | * On ST_NCI, IRQ goes in idle state when read starts. |
35630df6 | 156 | */ |
ed06aeef | 157 | static irqreturn_t st_nci_irq_thread_fn(int irq, void *phy_id) |
35630df6 | 158 | { |
ed06aeef | 159 | struct st_nci_i2c_phy *phy = phy_id; |
35630df6 CR |
160 | struct sk_buff *skb = NULL; |
161 | int r; | |
162 | ||
7274496f | 163 | if (!phy || !phy->ndlc || irq != phy->i2c_dev->irq) { |
35630df6 CR |
164 | WARN_ON_ONCE(1); |
165 | return IRQ_NONE; | |
166 | } | |
167 | ||
4294e320 | 168 | if (phy->ndlc->hard_fault) |
35630df6 CR |
169 | return IRQ_HANDLED; |
170 | ||
183fe2d0 | 171 | if (!phy->ndlc->powered) { |
ed06aeef | 172 | st_nci_i2c_disable(phy); |
35630df6 CR |
173 | return IRQ_HANDLED; |
174 | } | |
175 | ||
ed06aeef | 176 | r = st_nci_i2c_read(phy, &skb); |
4294e320 | 177 | if (r == -EREMOTEIO || r == -ENOMEM || r == -EBADMSG) |
35630df6 | 178 | return IRQ_HANDLED; |
35630df6 CR |
179 | |
180 | ndlc_recv(phy->ndlc, skb); | |
181 | ||
182 | return IRQ_HANDLED; | |
183 | } | |
184 | ||
7a5e98da | 185 | static const struct nfc_phy_ops i2c_phy_ops = { |
ed06aeef CR |
186 | .write = st_nci_i2c_write, |
187 | .enable = st_nci_i2c_enable, | |
188 | .disable = st_nci_i2c_disable, | |
35630df6 CR |
189 | }; |
190 | ||
85d23e77 AS |
191 | static const struct acpi_gpio_params reset_gpios = { 1, 0, false }; |
192 | ||
193 | static const struct acpi_gpio_mapping acpi_st_nci_gpios[] = { | |
194 | { "reset-gpios", &reset_gpios, 1 }, | |
195 | {}, | |
196 | }; | |
197 | ||
75cc560f | 198 | static int st_nci_i2c_probe(struct i2c_client *client) |
35630df6 | 199 | { |
75719b2b | 200 | struct device *dev = &client->dev; |
ed06aeef | 201 | struct st_nci_i2c_phy *phy; |
35630df6 CR |
202 | int r; |
203 | ||
35630df6 CR |
204 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { |
205 | nfc_err(&client->dev, "Need I2C_FUNC_I2C\n"); | |
206 | return -ENODEV; | |
207 | } | |
208 | ||
c745120e | 209 | phy = devm_kzalloc(dev, sizeof(struct st_nci_i2c_phy), GFP_KERNEL); |
3590ebc0 | 210 | if (!phy) |
35630df6 | 211 | return -ENOMEM; |
35630df6 CR |
212 | |
213 | phy->i2c_dev = client; | |
214 | ||
215 | i2c_set_clientdata(client, phy); | |
216 | ||
c745120e AS |
217 | r = devm_acpi_dev_add_driver_gpios(dev, acpi_st_nci_gpios); |
218 | if (r) | |
219 | dev_dbg(dev, "Unable to add GPIO mapping table\n"); | |
220 | ||
221 | /* Get RESET GPIO */ | |
222 | phy->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); | |
223 | if (IS_ERR(phy->gpiod_reset)) { | |
224 | nfc_err(dev, "Unable to get RESET GPIO\n"); | |
35630df6 CR |
225 | return -ENODEV; |
226 | } | |
227 | ||
75719b2b AS |
228 | phy->se_status.is_ese_present = |
229 | device_property_read_bool(dev, "ese-present"); | |
230 | phy->se_status.is_uicc_present = | |
231 | device_property_read_bool(dev, "uicc-present"); | |
232 | ||
7274496f | 233 | r = ndlc_probe(phy, &i2c_phy_ops, &client->dev, |
30458aac | 234 | ST_NCI_FRAME_HEADROOM, ST_NCI_FRAME_TAILROOM, |
3648dc6d | 235 | &phy->ndlc, &phy->se_status); |
7274496f CR |
236 | if (r < 0) { |
237 | nfc_err(&client->dev, "Unable to register ndlc layer\n"); | |
238 | return r; | |
239 | } | |
240 | ||
bb2496c3 | 241 | phy->irq_active = true; |
35630df6 | 242 | r = devm_request_threaded_irq(&client->dev, client->irq, NULL, |
ed06aeef | 243 | st_nci_irq_thread_fn, |
1af9fea6 | 244 | IRQF_ONESHOT, |
ed06aeef | 245 | ST_NCI_DRIVER_NAME, phy); |
7274496f | 246 | if (r < 0) |
35630df6 | 247 | nfc_err(&client->dev, "Unable to register IRQ handler\n"); |
35630df6 | 248 | |
7274496f | 249 | return r; |
35630df6 CR |
250 | } |
251 | ||
ed5c2f5f | 252 | static void st_nci_i2c_remove(struct i2c_client *client) |
35630df6 | 253 | { |
ed06aeef | 254 | struct st_nci_i2c_phy *phy = i2c_get_clientdata(client); |
35630df6 | 255 | |
35630df6 | 256 | ndlc_remove(phy->ndlc); |
35630df6 CR |
257 | } |
258 | ||
98455307 | 259 | static const struct i2c_device_id st_nci_i2c_id_table[] = { |
0d6b1eb6 | 260 | { ST_NCI_DRIVER_NAME }, |
3252897f CR |
261 | {} |
262 | }; | |
263 | MODULE_DEVICE_TABLE(i2c, st_nci_i2c_id_table); | |
264 | ||
255fcc7b | 265 | static const struct acpi_device_id st_nci_i2c_acpi_match[] __maybe_unused = { |
ed6a2f3f CR |
266 | {"SMO2101"}, |
267 | {"SMO2102"}, | |
268 | {} | |
269 | }; | |
270 | MODULE_DEVICE_TABLE(acpi, st_nci_i2c_acpi_match); | |
271 | ||
255fcc7b | 272 | static const struct of_device_id of_st_nci_i2c_match[] __maybe_unused = { |
1a94cb60 | 273 | { .compatible = "st,st21nfcb-i2c", }, |
35630df6 | 274 | { .compatible = "st,st21nfcb_i2c", }, |
ed06aeef | 275 | { .compatible = "st,st21nfcc-i2c", }, |
35630df6 CR |
276 | {} |
277 | }; | |
ed06aeef | 278 | MODULE_DEVICE_TABLE(of, of_st_nci_i2c_match); |
35630df6 | 279 | |
ed06aeef | 280 | static struct i2c_driver st_nci_i2c_driver = { |
35630df6 | 281 | .driver = { |
ed06aeef CR |
282 | .name = ST_NCI_I2C_DRIVER_NAME, |
283 | .of_match_table = of_match_ptr(of_st_nci_i2c_match), | |
ed6a2f3f | 284 | .acpi_match_table = ACPI_PTR(st_nci_i2c_acpi_match), |
35630df6 | 285 | }, |
efc3001f | 286 | .probe = st_nci_i2c_probe, |
ed06aeef CR |
287 | .id_table = st_nci_i2c_id_table, |
288 | .remove = st_nci_i2c_remove, | |
35630df6 | 289 | }; |
ed06aeef | 290 | module_i2c_driver(st_nci_i2c_driver); |
35630df6 CR |
291 | |
292 | MODULE_LICENSE("GPL"); | |
293 | MODULE_DESCRIPTION(DRIVER_DESC); |