• Home
  • Raw
  • Download

Lines Matching +full:phy +full:- +full:i2c

1 // SPDX-License-Identifier: GPL-2.0-only
3 * I2C Link Layer for ST21NFCA HCI based Driver
9 #include <linux/crc-ccitt.h>
11 #include <linux/i2c.h>
35 * - insert ST21NFCA_ESCAPE_BYTE_STUFFING (escape byte)
36 * - xor byte with ST21NFCA_BYTE_STUFFING_MASK
63 * crc might have fail because i2c macro
72 * < 0 if hardware error occured (e.g. i2c err)
85 print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET, \
86 16, 1, (skb)->data, (skb)->len, 0); \
95 static int st21nfca_hci_platform_init(struct st21nfca_i2c_phy *phy) in st21nfca_hci_platform_init() argument
100 int i, r = -1; in st21nfca_hci_platform_init()
103 r = i2c_master_send(phy->i2c_dev, reboot_cmd, in st21nfca_hci_platform_init()
113 r = -1; in st21nfca_hci_platform_init()
115 r = i2c_master_recv(phy->i2c_dev, tmp, in st21nfca_hci_platform_init()
128 return -ENODEV; in st21nfca_hci_platform_init()
136 struct st21nfca_i2c_phy *phy = phy_id; in st21nfca_hci_i2c_enable() local
138 gpiod_set_value(phy->gpiod_ena, 1); in st21nfca_hci_i2c_enable()
139 phy->powered = 1; in st21nfca_hci_i2c_enable()
140 phy->run_mode = ST21NFCA_HCI_MODE; in st21nfca_hci_i2c_enable()
149 struct st21nfca_i2c_phy *phy = phy_id; in st21nfca_hci_i2c_disable() local
151 gpiod_set_value(phy->gpiod_ena, 0); in st21nfca_hci_i2c_disable()
153 phy->powered = 0; in st21nfca_hci_i2c_disable()
163 crc = crc_ccitt(0xffff, skb->data, skb->len); in st21nfca_hci_add_len_crc()
176 skb_trim(skb, skb->len - ST21NFCA_FRAME_TAILROOM); in st21nfca_hci_remove_len_crc()
186 int r = -1, i, j; in st21nfca_hci_i2c_write()
187 struct st21nfca_i2c_phy *phy = phy_id; in st21nfca_hci_i2c_write() local
188 struct i2c_client *client = phy->i2c_dev; in st21nfca_hci_i2c_write()
193 if (phy->hard_fault != 0) in st21nfca_hci_i2c_write()
194 return phy->hard_fault; in st21nfca_hci_i2c_write()
214 tmp[0] = skb->data[0]; in st21nfca_hci_i2c_write()
215 for (i = 1, j = 1; i < skb->len - 1; i++, j++) { in st21nfca_hci_i2c_write()
216 if (skb->data[i] == ST21NFCA_SOF_EOF in st21nfca_hci_i2c_write()
217 || skb->data[i] == ST21NFCA_ESCAPE_BYTE_STUFFING) { in st21nfca_hci_i2c_write()
220 tmp[j] = skb->data[i] ^ ST21NFCA_BYTE_STUFFING_MASK; in st21nfca_hci_i2c_write()
222 tmp[j] = skb->data[i]; in st21nfca_hci_i2c_write()
225 tmp[j] = skb->data[i]; in st21nfca_hci_i2c_write()
232 mutex_lock(&phy->phy_lock); in st21nfca_hci_i2c_write()
238 mutex_unlock(&phy->phy_lock); in st21nfca_hci_i2c_write()
242 r = -EREMOTEIO; in st21nfca_hci_i2c_write()
269 crc = crc_ccitt(0xffff, buf, buflen - 2); in check_crc()
272 if (buf[buflen - 2] != (crc & 0xff) || buf[buflen - 1] != (crc >> 8)) { in check_crc()
274 ": CRC error 0x%x != 0x%x 0x%x\n", crc, buf[buflen - 1], in check_crc()
275 buf[buflen - 2]); in check_crc()
280 return -EPERM; in check_crc()
291 * -EBADMSG : frame was incorrect and discarded
297 if (skb->len < 1 || (skb->len > 1 && skb->data[1] != 0)) in st21nfca_hci_i2c_repack()
298 return -EBADMSG; in st21nfca_hci_i2c_repack()
300 size = get_frame_size(skb->data, skb->len); in st21nfca_hci_i2c_repack()
304 for (i = 1, j = 0; i < skb->len; i++) { in st21nfca_hci_i2c_repack()
305 if (skb->data[i + j] == in st21nfca_hci_i2c_repack()
307 skb->data[i] = skb->data[i + j + 1] in st21nfca_hci_i2c_repack()
312 skb->data[i] = skb->data[i + j]; in st21nfca_hci_i2c_repack()
315 skb_trim(skb, i - j); in st21nfca_hci_i2c_repack()
319 r = check_crc(skb->data, skb->len); in st21nfca_hci_i2c_repack()
322 return -EBADMSG; in st21nfca_hci_i2c_repack()
328 skb_trim(skb, skb->len - 2); in st21nfca_hci_i2c_repack()
329 return skb->len; in st21nfca_hci_i2c_repack()
336 * that i2c bus will be flushed and that next read will start on a new frame.
341 * -EAGAIN : if received frame is incomplete (not find ST21NFCA_SOF_EOF
343 * -EREMOTEIO : i2c read error (fatal)
344 * -EBADMSG : frame was incorrect and discarded
346 * -EIO : if no ST21NFCA_SOF_EOF is found after reaching
349 static int st21nfca_hci_i2c_read(struct st21nfca_i2c_phy *phy, in st21nfca_hci_i2c_read() argument
355 struct i2c_client *client = phy->i2c_dev; in st21nfca_hci_i2c_read()
357 if (phy->current_read_len < ARRAY_SIZE(len_seq)) { in st21nfca_hci_i2c_read()
358 len = len_seq[phy->current_read_len]; in st21nfca_hci_i2c_read()
362 * Operation on I2C interface may fail in case of operation on in st21nfca_hci_i2c_read()
366 mutex_lock(&phy->phy_lock); in st21nfca_hci_i2c_read()
372 mutex_unlock(&phy->phy_lock); in st21nfca_hci_i2c_read()
375 phy->current_read_len = 0; in st21nfca_hci_i2c_read()
376 return -EREMOTEIO; in st21nfca_hci_i2c_read()
383 if (!phy->current_read_len && !IS_START_OF_FRAME(buf)) { in st21nfca_hci_i2c_read()
385 phy->current_read_len = 0; in st21nfca_hci_i2c_read()
386 return -EIO; in st21nfca_hci_i2c_read()
387 } else if (phy->current_read_len && IS_START_OF_FRAME(buf)) { in st21nfca_hci_i2c_read()
394 phy->current_read_len = 0; in st21nfca_hci_i2c_read()
399 if (skb->data[skb->len - 1] == ST21NFCA_SOF_EOF) { in st21nfca_hci_i2c_read()
400 phy->current_read_len = 0; in st21nfca_hci_i2c_read()
403 phy->current_read_len++; in st21nfca_hci_i2c_read()
404 return -EAGAIN; in st21nfca_hci_i2c_read()
406 return -EIO; in st21nfca_hci_i2c_read()
411 * seems. The frame format is data-crc, and corruption can occur anywhere
412 * while transiting on i2c bus, such that we could read an invalid data.
425 struct st21nfca_i2c_phy *phy = phy_id; in st21nfca_hci_irq_thread_fn() local
430 if (!phy || irq != phy->i2c_dev->irq) { in st21nfca_hci_irq_thread_fn()
435 client = phy->i2c_dev; in st21nfca_hci_irq_thread_fn()
436 dev_dbg(&client->dev, "IRQ\n"); in st21nfca_hci_irq_thread_fn()
438 if (phy->hard_fault != 0) in st21nfca_hci_irq_thread_fn()
441 r = st21nfca_hci_i2c_read(phy, phy->pending_skb); in st21nfca_hci_irq_thread_fn()
442 if (r == -EREMOTEIO) { in st21nfca_hci_irq_thread_fn()
443 phy->hard_fault = r; in st21nfca_hci_irq_thread_fn()
445 nfc_hci_recv_frame(phy->hdev, NULL); in st21nfca_hci_irq_thread_fn()
448 } else if (r == -EAGAIN || r == -EIO) { in st21nfca_hci_irq_thread_fn()
450 } else if (r == -EBADMSG && phy->crc_trials < ARRAY_SIZE(wait_tab)) { in st21nfca_hci_irq_thread_fn()
452 * With ST21NFCA, only one interface (I2C, RF or SWP) in st21nfca_hci_irq_thread_fn()
454 * Having incorrect crc is usually due to i2c macrocell in st21nfca_hci_irq_thread_fn()
456 * It may generate corrupted data on i2c. in st21nfca_hci_irq_thread_fn()
457 * We give sometime to get i2c back. in st21nfca_hci_irq_thread_fn()
460 msleep(wait_tab[phy->crc_trials]); in st21nfca_hci_irq_thread_fn()
461 phy->crc_trials++; in st21nfca_hci_irq_thread_fn()
462 phy->current_read_len = 0; in st21nfca_hci_irq_thread_fn()
463 kfree_skb(phy->pending_skb); in st21nfca_hci_irq_thread_fn()
470 nfc_hci_recv_frame(phy->hdev, phy->pending_skb); in st21nfca_hci_irq_thread_fn()
471 phy->crc_trials = 0; in st21nfca_hci_irq_thread_fn()
473 kfree_skb(phy->pending_skb); in st21nfca_hci_irq_thread_fn()
476 phy->pending_skb = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE * 2, GFP_KERNEL); in st21nfca_hci_irq_thread_fn()
477 if (phy->pending_skb == NULL) { in st21nfca_hci_irq_thread_fn()
478 phy->hard_fault = -ENOMEM; in st21nfca_hci_irq_thread_fn()
479 nfc_hci_recv_frame(phy->hdev, NULL); in st21nfca_hci_irq_thread_fn()
494 { "enable-gpios", &enable_gpios, 1 },
501 struct device *dev = &client->dev; in st21nfca_hci_i2c_probe()
502 struct st21nfca_i2c_phy *phy; in st21nfca_hci_i2c_probe() local
505 dev_dbg(&client->dev, "%s\n", __func__); in st21nfca_hci_i2c_probe()
506 dev_dbg(&client->dev, "IRQ: %d\n", client->irq); in st21nfca_hci_i2c_probe()
508 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { in st21nfca_hci_i2c_probe()
509 nfc_err(&client->dev, "Need I2C_FUNC_I2C\n"); in st21nfca_hci_i2c_probe()
510 return -ENODEV; in st21nfca_hci_i2c_probe()
513 phy = devm_kzalloc(&client->dev, sizeof(struct st21nfca_i2c_phy), in st21nfca_hci_i2c_probe()
515 if (!phy) in st21nfca_hci_i2c_probe()
516 return -ENOMEM; in st21nfca_hci_i2c_probe()
518 phy->i2c_dev = client; in st21nfca_hci_i2c_probe()
519 phy->pending_skb = alloc_skb(ST21NFCA_HCI_LLC_MAX_SIZE * 2, GFP_KERNEL); in st21nfca_hci_i2c_probe()
520 if (phy->pending_skb == NULL) in st21nfca_hci_i2c_probe()
521 return -ENOMEM; in st21nfca_hci_i2c_probe()
523 phy->current_read_len = 0; in st21nfca_hci_i2c_probe()
524 phy->crc_trials = 0; in st21nfca_hci_i2c_probe()
525 mutex_init(&phy->phy_lock); in st21nfca_hci_i2c_probe()
526 i2c_set_clientdata(client, phy); in st21nfca_hci_i2c_probe()
533 phy->gpiod_ena = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); in st21nfca_hci_i2c_probe()
534 if (IS_ERR(phy->gpiod_ena)) { in st21nfca_hci_i2c_probe()
536 r = PTR_ERR(phy->gpiod_ena); in st21nfca_hci_i2c_probe()
540 phy->se_status.is_ese_present = in st21nfca_hci_i2c_probe()
541 device_property_read_bool(&client->dev, "ese-present"); in st21nfca_hci_i2c_probe()
542 phy->se_status.is_uicc_present = in st21nfca_hci_i2c_probe()
543 device_property_read_bool(&client->dev, "uicc-present"); in st21nfca_hci_i2c_probe()
545 r = st21nfca_hci_platform_init(phy); in st21nfca_hci_i2c_probe()
547 nfc_err(&client->dev, "Unable to reboot st21nfca\n"); in st21nfca_hci_i2c_probe()
551 r = devm_request_threaded_irq(&client->dev, client->irq, NULL, in st21nfca_hci_i2c_probe()
554 ST21NFCA_HCI_DRIVER_NAME, phy); in st21nfca_hci_i2c_probe()
556 nfc_err(&client->dev, "Unable to register IRQ handler\n"); in st21nfca_hci_i2c_probe()
560 r = st21nfca_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME, in st21nfca_hci_i2c_probe()
564 &phy->hdev, in st21nfca_hci_i2c_probe()
565 &phy->se_status); in st21nfca_hci_i2c_probe()
572 kfree_skb(phy->pending_skb); in st21nfca_hci_i2c_probe()
578 struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client); in st21nfca_hci_i2c_remove() local
580 dev_dbg(&client->dev, "%s\n", __func__); in st21nfca_hci_i2c_remove()
582 st21nfca_hci_remove(phy->hdev); in st21nfca_hci_i2c_remove()
584 if (phy->powered) in st21nfca_hci_i2c_remove()
585 st21nfca_hci_i2c_disable(phy); in st21nfca_hci_i2c_remove()
586 if (phy->pending_skb) in st21nfca_hci_i2c_remove()
587 kfree_skb(phy->pending_skb); in st21nfca_hci_i2c_remove()
596 MODULE_DEVICE_TABLE(i2c, st21nfca_hci_i2c_id_table);
605 { .compatible = "st,st21nfca-i2c", },