1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * SPI Link Layer for ST NCI based Driver |
4 | * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved. |
5 | */ |
6 | |
7 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
8 | |
9 | #include <linux/module.h> |
10 | #include <linux/spi/spi.h> |
11 | #include <linux/gpio/consumer.h> |
12 | #include <linux/acpi.h> |
13 | #include <linux/interrupt.h> |
14 | #include <linux/delay.h> |
15 | #include <linux/nfc.h> |
16 | #include <linux/of.h> |
17 | #include <net/nfc/nci.h> |
18 | |
19 | #include "st-nci.h" |
20 | |
21 | #define DRIVER_DESC "NCI NFC driver for ST_NCI" |
22 | |
23 | /* ndlc header */ |
24 | #define ST_NCI_FRAME_HEADROOM 1 |
25 | #define ST_NCI_FRAME_TAILROOM 0 |
26 | |
27 | #define ST_NCI_SPI_MIN_SIZE 4 /* PCB(1) + NCI Packet header(3) */ |
28 | #define ST_NCI_SPI_MAX_SIZE 250 /* req 4.2.1 */ |
29 | |
30 | #define ST_NCI_DRIVER_NAME "st_nci" |
31 | #define ST_NCI_SPI_DRIVER_NAME "st_nci_spi" |
32 | |
33 | struct st_nci_spi_phy { |
34 | struct spi_device *spi_dev; |
35 | struct llt_ndlc *ndlc; |
36 | |
37 | bool irq_active; |
38 | |
39 | struct gpio_desc *gpiod_reset; |
40 | |
41 | struct st_nci_se_status se_status; |
42 | }; |
43 | |
44 | static int st_nci_spi_enable(void *phy_id) |
45 | { |
46 | struct st_nci_spi_phy *phy = phy_id; |
47 | |
48 | gpiod_set_value(desc: phy->gpiod_reset, value: 0); |
49 | usleep_range(min: 10000, max: 15000); |
50 | gpiod_set_value(desc: phy->gpiod_reset, value: 1); |
51 | usleep_range(min: 80000, max: 85000); |
52 | |
53 | if (phy->ndlc->powered == 0 && phy->irq_active == 0) { |
54 | enable_irq(irq: phy->spi_dev->irq); |
55 | phy->irq_active = true; |
56 | } |
57 | |
58 | return 0; |
59 | } |
60 | |
61 | static void st_nci_spi_disable(void *phy_id) |
62 | { |
63 | struct st_nci_spi_phy *phy = phy_id; |
64 | |
65 | disable_irq_nosync(irq: phy->spi_dev->irq); |
66 | phy->irq_active = false; |
67 | } |
68 | |
69 | /* |
70 | * Writing a frame must not return the number of written bytes. |
71 | * It must return either zero for success, or <0 for error. |
72 | * In addition, it must not alter the skb |
73 | */ |
74 | static int st_nci_spi_write(void *phy_id, struct sk_buff *skb) |
75 | { |
76 | int r; |
77 | struct st_nci_spi_phy *phy = phy_id; |
78 | struct spi_device *dev = phy->spi_dev; |
79 | struct sk_buff *skb_rx; |
80 | u8 buf[ST_NCI_SPI_MAX_SIZE + NCI_DATA_HDR_SIZE + |
81 | ST_NCI_FRAME_HEADROOM + ST_NCI_FRAME_TAILROOM]; |
82 | struct spi_transfer spi_xfer = { |
83 | .tx_buf = skb->data, |
84 | .rx_buf = buf, |
85 | .len = skb->len, |
86 | }; |
87 | |
88 | if (phy->ndlc->hard_fault != 0) |
89 | return phy->ndlc->hard_fault; |
90 | |
91 | r = spi_sync_transfer(spi: dev, xfers: &spi_xfer, num_xfers: 1); |
92 | /* |
93 | * We may have received some valuable data on miso line. |
94 | * Send them back in the ndlc state machine. |
95 | */ |
96 | if (!r) { |
97 | skb_rx = alloc_skb(size: skb->len, GFP_KERNEL); |
98 | if (!skb_rx) |
99 | return -ENOMEM; |
100 | |
101 | skb_put(skb: skb_rx, len: skb->len); |
102 | memcpy(skb_rx->data, buf, skb->len); |
103 | ndlc_recv(ndlc: phy->ndlc, skb: skb_rx); |
104 | } |
105 | |
106 | return r; |
107 | } |
108 | |
109 | /* |
110 | * Reads an ndlc frame and returns it in a newly allocated sk_buff. |
111 | * returns: |
112 | * 0 : if received frame is complete |
113 | * -EREMOTEIO : i2c read error (fatal) |
114 | * -EBADMSG : frame was incorrect and discarded |
115 | * -ENOMEM : cannot allocate skb, frame dropped |
116 | */ |
117 | static int st_nci_spi_read(struct st_nci_spi_phy *phy, |
118 | struct sk_buff **skb) |
119 | { |
120 | int r; |
121 | u8 len; |
122 | u8 buf[ST_NCI_SPI_MAX_SIZE]; |
123 | struct spi_device *dev = phy->spi_dev; |
124 | struct spi_transfer spi_xfer = { |
125 | .rx_buf = buf, |
126 | .len = ST_NCI_SPI_MIN_SIZE, |
127 | }; |
128 | |
129 | r = spi_sync_transfer(spi: dev, xfers: &spi_xfer, num_xfers: 1); |
130 | if (r < 0) |
131 | return -EREMOTEIO; |
132 | |
133 | len = be16_to_cpu(*(__be16 *) (buf + 2)); |
134 | if (len > ST_NCI_SPI_MAX_SIZE) { |
135 | nfc_err(&dev->dev, "invalid frame len\n" ); |
136 | phy->ndlc->hard_fault = 1; |
137 | return -EBADMSG; |
138 | } |
139 | |
140 | *skb = alloc_skb(ST_NCI_SPI_MIN_SIZE + len, GFP_KERNEL); |
141 | if (*skb == NULL) |
142 | return -ENOMEM; |
143 | |
144 | skb_reserve(skb: *skb, ST_NCI_SPI_MIN_SIZE); |
145 | skb_put(skb: *skb, ST_NCI_SPI_MIN_SIZE); |
146 | memcpy((*skb)->data, buf, ST_NCI_SPI_MIN_SIZE); |
147 | |
148 | if (!len) |
149 | return 0; |
150 | |
151 | spi_xfer.len = len; |
152 | r = spi_sync_transfer(spi: dev, xfers: &spi_xfer, num_xfers: 1); |
153 | if (r < 0) { |
154 | kfree_skb(skb: *skb); |
155 | return -EREMOTEIO; |
156 | } |
157 | |
158 | skb_put(skb: *skb, len); |
159 | memcpy((*skb)->data + ST_NCI_SPI_MIN_SIZE, buf, len); |
160 | |
161 | return 0; |
162 | } |
163 | |
164 | /* |
165 | * Reads an ndlc frame from the chip. |
166 | * |
167 | * On ST21NFCB, IRQ goes in idle state when read starts. |
168 | */ |
169 | static irqreturn_t st_nci_irq_thread_fn(int irq, void *phy_id) |
170 | { |
171 | struct st_nci_spi_phy *phy = phy_id; |
172 | struct sk_buff *skb = NULL; |
173 | int r; |
174 | |
175 | if (!phy || !phy->ndlc || irq != phy->spi_dev->irq) { |
176 | WARN_ON_ONCE(1); |
177 | return IRQ_NONE; |
178 | } |
179 | |
180 | if (phy->ndlc->hard_fault) |
181 | return IRQ_HANDLED; |
182 | |
183 | if (!phy->ndlc->powered) { |
184 | st_nci_spi_disable(phy_id: phy); |
185 | return IRQ_HANDLED; |
186 | } |
187 | |
188 | r = st_nci_spi_read(phy, skb: &skb); |
189 | if (r == -EREMOTEIO || r == -ENOMEM || r == -EBADMSG) |
190 | return IRQ_HANDLED; |
191 | |
192 | ndlc_recv(ndlc: phy->ndlc, skb); |
193 | |
194 | return IRQ_HANDLED; |
195 | } |
196 | |
197 | static const struct nfc_phy_ops spi_phy_ops = { |
198 | .write = st_nci_spi_write, |
199 | .enable = st_nci_spi_enable, |
200 | .disable = st_nci_spi_disable, |
201 | }; |
202 | |
203 | static const struct acpi_gpio_params reset_gpios = { 1, 0, false }; |
204 | |
205 | static const struct acpi_gpio_mapping acpi_st_nci_gpios[] = { |
206 | { "reset-gpios" , &reset_gpios, 1 }, |
207 | {}, |
208 | }; |
209 | |
210 | static int st_nci_spi_probe(struct spi_device *dev) |
211 | { |
212 | struct st_nci_spi_phy *phy; |
213 | int r; |
214 | |
215 | /* Check SPI platform functionnalities */ |
216 | if (!dev) { |
217 | pr_debug("%s: dev is NULL. Device is not accessible.\n" , |
218 | __func__); |
219 | return -ENODEV; |
220 | } |
221 | |
222 | phy = devm_kzalloc(dev: &dev->dev, size: sizeof(struct st_nci_spi_phy), |
223 | GFP_KERNEL); |
224 | if (!phy) |
225 | return -ENOMEM; |
226 | |
227 | phy->spi_dev = dev; |
228 | |
229 | spi_set_drvdata(spi: dev, data: phy); |
230 | |
231 | r = devm_acpi_dev_add_driver_gpios(dev: &dev->dev, gpios: acpi_st_nci_gpios); |
232 | if (r) |
233 | dev_dbg(&dev->dev, "Unable to add GPIO mapping table\n" ); |
234 | |
235 | /* Get RESET GPIO */ |
236 | phy->gpiod_reset = devm_gpiod_get(dev: &dev->dev, con_id: "reset" , flags: GPIOD_OUT_HIGH); |
237 | if (IS_ERR(ptr: phy->gpiod_reset)) { |
238 | nfc_err(&dev->dev, "Unable to get RESET GPIO\n" ); |
239 | return PTR_ERR(ptr: phy->gpiod_reset); |
240 | } |
241 | |
242 | phy->se_status.is_ese_present = |
243 | device_property_read_bool(dev: &dev->dev, propname: "ese-present" ); |
244 | phy->se_status.is_uicc_present = |
245 | device_property_read_bool(dev: &dev->dev, propname: "uicc-present" ); |
246 | |
247 | r = ndlc_probe(phy_id: phy, phy_ops: &spi_phy_ops, dev: &dev->dev, |
248 | ST_NCI_FRAME_HEADROOM, ST_NCI_FRAME_TAILROOM, |
249 | ndlc_id: &phy->ndlc, se_status: &phy->se_status); |
250 | if (r < 0) { |
251 | nfc_err(&dev->dev, "Unable to register ndlc layer\n" ); |
252 | return r; |
253 | } |
254 | |
255 | phy->irq_active = true; |
256 | r = devm_request_threaded_irq(dev: &dev->dev, irq: dev->irq, NULL, |
257 | thread_fn: st_nci_irq_thread_fn, |
258 | IRQF_ONESHOT, |
259 | ST_NCI_SPI_DRIVER_NAME, dev_id: phy); |
260 | if (r < 0) |
261 | nfc_err(&dev->dev, "Unable to register IRQ handler\n" ); |
262 | |
263 | return r; |
264 | } |
265 | |
266 | static void st_nci_spi_remove(struct spi_device *dev) |
267 | { |
268 | struct st_nci_spi_phy *phy = spi_get_drvdata(spi: dev); |
269 | |
270 | ndlc_remove(ndlc: phy->ndlc); |
271 | } |
272 | |
273 | static struct spi_device_id st_nci_spi_id_table[] = { |
274 | {ST_NCI_SPI_DRIVER_NAME, 0}, |
275 | {"st21nfcb-spi" , 0}, |
276 | {} |
277 | }; |
278 | MODULE_DEVICE_TABLE(spi, st_nci_spi_id_table); |
279 | |
280 | static const struct acpi_device_id st_nci_spi_acpi_match[] __maybe_unused = { |
281 | {"SMO2101" , 0}, |
282 | {} |
283 | }; |
284 | MODULE_DEVICE_TABLE(acpi, st_nci_spi_acpi_match); |
285 | |
286 | static const struct of_device_id of_st_nci_spi_match[] __maybe_unused = { |
287 | { .compatible = "st,st21nfcb-spi" , }, |
288 | {} |
289 | }; |
290 | MODULE_DEVICE_TABLE(of, of_st_nci_spi_match); |
291 | |
292 | static struct spi_driver st_nci_spi_driver = { |
293 | .driver = { |
294 | .name = ST_NCI_SPI_DRIVER_NAME, |
295 | .of_match_table = of_match_ptr(of_st_nci_spi_match), |
296 | .acpi_match_table = ACPI_PTR(st_nci_spi_acpi_match), |
297 | }, |
298 | .probe = st_nci_spi_probe, |
299 | .id_table = st_nci_spi_id_table, |
300 | .remove = st_nci_spi_remove, |
301 | }; |
302 | module_spi_driver(st_nci_spi_driver); |
303 | |
304 | MODULE_LICENSE("GPL" ); |
305 | MODULE_DESCRIPTION(DRIVER_DESC); |
306 | |