146fe7771SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
22bc4d4f8SChristophe Ricard /*
32bc4d4f8SChristophe Ricard * SPI Link Layer for ST NCI based Driver
42bc4d4f8SChristophe Ricard * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
52bc4d4f8SChristophe Ricard */
62bc4d4f8SChristophe Ricard
72bc4d4f8SChristophe Ricard #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
82bc4d4f8SChristophe Ricard
92bc4d4f8SChristophe Ricard #include <linux/module.h>
102bc4d4f8SChristophe Ricard #include <linux/spi/spi.h>
1160cd6d89SChristophe Ricard #include <linux/gpio/consumer.h>
1260cd6d89SChristophe Ricard #include <linux/acpi.h>
132bc4d4f8SChristophe Ricard #include <linux/interrupt.h>
142bc4d4f8SChristophe Ricard #include <linux/delay.h>
152bc4d4f8SChristophe Ricard #include <linux/nfc.h>
16a89e68f1SAndy Shevchenko #include <linux/of.h>
17a1269dd1SChristophe Ricard #include <net/nfc/nci.h>
182bc4d4f8SChristophe Ricard
19e67e7e59SChristophe Ricard #include "st-nci.h"
202bc4d4f8SChristophe Ricard
212bc4d4f8SChristophe Ricard #define DRIVER_DESC "NCI NFC driver for ST_NCI"
222bc4d4f8SChristophe Ricard
232bc4d4f8SChristophe Ricard /* ndlc header */
242bc4d4f8SChristophe Ricard #define ST_NCI_FRAME_HEADROOM 1
252bc4d4f8SChristophe Ricard #define ST_NCI_FRAME_TAILROOM 0
262bc4d4f8SChristophe Ricard
272bc4d4f8SChristophe Ricard #define ST_NCI_SPI_MIN_SIZE 4 /* PCB(1) + NCI Packet header(3) */
282bc4d4f8SChristophe Ricard #define ST_NCI_SPI_MAX_SIZE 250 /* req 4.2.1 */
292bc4d4f8SChristophe Ricard
3061a04101SAndy Shevchenko #define ST_NCI_DRIVER_NAME "st_nci"
312bc4d4f8SChristophe Ricard #define ST_NCI_SPI_DRIVER_NAME "st_nci_spi"
322bc4d4f8SChristophe Ricard
332bc4d4f8SChristophe Ricard struct st_nci_spi_phy {
342bc4d4f8SChristophe Ricard struct spi_device *spi_dev;
352bc4d4f8SChristophe Ricard struct llt_ndlc *ndlc;
362bc4d4f8SChristophe Ricard
37bb2496c3SChristophe Ricard bool irq_active;
38bb2496c3SChristophe Ricard
39a89e68f1SAndy Shevchenko struct gpio_desc *gpiod_reset;
403648dc6dSChristophe Ricard
413648dc6dSChristophe Ricard struct st_nci_se_status se_status;
422bc4d4f8SChristophe Ricard };
432bc4d4f8SChristophe Ricard
st_nci_spi_enable(void * phy_id)442bc4d4f8SChristophe Ricard static int st_nci_spi_enable(void *phy_id)
452bc4d4f8SChristophe Ricard {
462bc4d4f8SChristophe Ricard struct st_nci_spi_phy *phy = phy_id;
472bc4d4f8SChristophe Ricard
48a89e68f1SAndy Shevchenko gpiod_set_value(phy->gpiod_reset, 0);
492bc4d4f8SChristophe Ricard usleep_range(10000, 15000);
50a89e68f1SAndy Shevchenko gpiod_set_value(phy->gpiod_reset, 1);
512bc4d4f8SChristophe Ricard usleep_range(80000, 85000);
522bc4d4f8SChristophe Ricard
53bb2496c3SChristophe Ricard if (phy->ndlc->powered == 0 && phy->irq_active == 0) {
542bc4d4f8SChristophe Ricard enable_irq(phy->spi_dev->irq);
55bb2496c3SChristophe Ricard phy->irq_active = true;
56bb2496c3SChristophe Ricard }
572bc4d4f8SChristophe Ricard
582bc4d4f8SChristophe Ricard return 0;
592bc4d4f8SChristophe Ricard }
602bc4d4f8SChristophe Ricard
st_nci_spi_disable(void * phy_id)612bc4d4f8SChristophe Ricard static void st_nci_spi_disable(void *phy_id)
622bc4d4f8SChristophe Ricard {
632bc4d4f8SChristophe Ricard struct st_nci_spi_phy *phy = phy_id;
642bc4d4f8SChristophe Ricard
652bc4d4f8SChristophe Ricard disable_irq_nosync(phy->spi_dev->irq);
66bb2496c3SChristophe Ricard phy->irq_active = false;
672bc4d4f8SChristophe Ricard }
682bc4d4f8SChristophe Ricard
692bc4d4f8SChristophe Ricard /*
702bc4d4f8SChristophe Ricard * Writing a frame must not return the number of written bytes.
712bc4d4f8SChristophe Ricard * It must return either zero for success, or <0 for error.
722bc4d4f8SChristophe Ricard * In addition, it must not alter the skb
732bc4d4f8SChristophe Ricard */
st_nci_spi_write(void * phy_id,struct sk_buff * skb)742bc4d4f8SChristophe Ricard static int st_nci_spi_write(void *phy_id, struct sk_buff *skb)
752bc4d4f8SChristophe Ricard {
762bc4d4f8SChristophe Ricard int r;
772bc4d4f8SChristophe Ricard struct st_nci_spi_phy *phy = phy_id;
782bc4d4f8SChristophe Ricard struct spi_device *dev = phy->spi_dev;
792bc4d4f8SChristophe Ricard struct sk_buff *skb_rx;
80a1269dd1SChristophe Ricard u8 buf[ST_NCI_SPI_MAX_SIZE + NCI_DATA_HDR_SIZE +
81a1269dd1SChristophe Ricard ST_NCI_FRAME_HEADROOM + ST_NCI_FRAME_TAILROOM];
822bc4d4f8SChristophe Ricard struct spi_transfer spi_xfer = {
832bc4d4f8SChristophe Ricard .tx_buf = skb->data,
842bc4d4f8SChristophe Ricard .rx_buf = buf,
852bc4d4f8SChristophe Ricard .len = skb->len,
862bc4d4f8SChristophe Ricard };
872bc4d4f8SChristophe Ricard
882bc4d4f8SChristophe Ricard if (phy->ndlc->hard_fault != 0)
892bc4d4f8SChristophe Ricard return phy->ndlc->hard_fault;
902bc4d4f8SChristophe Ricard
912bc4d4f8SChristophe Ricard r = spi_sync_transfer(dev, &spi_xfer, 1);
922bc4d4f8SChristophe Ricard /*
932bc4d4f8SChristophe Ricard * We may have received some valuable data on miso line.
942bc4d4f8SChristophe Ricard * Send them back in the ndlc state machine.
952bc4d4f8SChristophe Ricard */
962bc4d4f8SChristophe Ricard if (!r) {
972bc4d4f8SChristophe Ricard skb_rx = alloc_skb(skb->len, GFP_KERNEL);
98eba43facSwengjianfeng if (!skb_rx)
99eba43facSwengjianfeng return -ENOMEM;
1002bc4d4f8SChristophe Ricard
1012bc4d4f8SChristophe Ricard skb_put(skb_rx, skb->len);
1022bc4d4f8SChristophe Ricard memcpy(skb_rx->data, buf, skb->len);
1032bc4d4f8SChristophe Ricard ndlc_recv(phy->ndlc, skb_rx);
1042bc4d4f8SChristophe Ricard }
1052bc4d4f8SChristophe Ricard
1062bc4d4f8SChristophe Ricard return r;
1072bc4d4f8SChristophe Ricard }
1082bc4d4f8SChristophe Ricard
1092bc4d4f8SChristophe Ricard /*
1102bc4d4f8SChristophe Ricard * Reads an ndlc frame and returns it in a newly allocated sk_buff.
1112bc4d4f8SChristophe Ricard * returns:
1122bc4d4f8SChristophe Ricard * 0 : if received frame is complete
1132bc4d4f8SChristophe Ricard * -EREMOTEIO : i2c read error (fatal)
1142bc4d4f8SChristophe Ricard * -EBADMSG : frame was incorrect and discarded
1152bc4d4f8SChristophe Ricard * -ENOMEM : cannot allocate skb, frame dropped
1162bc4d4f8SChristophe Ricard */
st_nci_spi_read(struct st_nci_spi_phy * phy,struct sk_buff ** skb)1172bc4d4f8SChristophe Ricard static int st_nci_spi_read(struct st_nci_spi_phy *phy,
1182bc4d4f8SChristophe Ricard struct sk_buff **skb)
1192bc4d4f8SChristophe Ricard {
1202bc4d4f8SChristophe Ricard int r;
1212bc4d4f8SChristophe Ricard u8 len;
1222bc4d4f8SChristophe Ricard u8 buf[ST_NCI_SPI_MAX_SIZE];
1232bc4d4f8SChristophe Ricard struct spi_device *dev = phy->spi_dev;
1242bc4d4f8SChristophe Ricard struct spi_transfer spi_xfer = {
1252bc4d4f8SChristophe Ricard .rx_buf = buf,
1262bc4d4f8SChristophe Ricard .len = ST_NCI_SPI_MIN_SIZE,
1272bc4d4f8SChristophe Ricard };
1282bc4d4f8SChristophe Ricard
1292bc4d4f8SChristophe Ricard r = spi_sync_transfer(dev, &spi_xfer, 1);
1302bc4d4f8SChristophe Ricard if (r < 0)
1312bc4d4f8SChristophe Ricard return -EREMOTEIO;
1322bc4d4f8SChristophe Ricard
1332bc4d4f8SChristophe Ricard len = be16_to_cpu(*(__be16 *) (buf + 2));
1342bc4d4f8SChristophe Ricard if (len > ST_NCI_SPI_MAX_SIZE) {
1352bc4d4f8SChristophe Ricard nfc_err(&dev->dev, "invalid frame len\n");
1362bc4d4f8SChristophe Ricard phy->ndlc->hard_fault = 1;
1372bc4d4f8SChristophe Ricard return -EBADMSG;
1382bc4d4f8SChristophe Ricard }
1392bc4d4f8SChristophe Ricard
1402bc4d4f8SChristophe Ricard *skb = alloc_skb(ST_NCI_SPI_MIN_SIZE + len, GFP_KERNEL);
1412bc4d4f8SChristophe Ricard if (*skb == NULL)
1422bc4d4f8SChristophe Ricard return -ENOMEM;
1432bc4d4f8SChristophe Ricard
1442bc4d4f8SChristophe Ricard skb_reserve(*skb, ST_NCI_SPI_MIN_SIZE);
1452bc4d4f8SChristophe Ricard skb_put(*skb, ST_NCI_SPI_MIN_SIZE);
1462bc4d4f8SChristophe Ricard memcpy((*skb)->data, buf, ST_NCI_SPI_MIN_SIZE);
1472bc4d4f8SChristophe Ricard
1482bc4d4f8SChristophe Ricard if (!len)
1492bc4d4f8SChristophe Ricard return 0;
1502bc4d4f8SChristophe Ricard
1512bc4d4f8SChristophe Ricard spi_xfer.len = len;
1522bc4d4f8SChristophe Ricard r = spi_sync_transfer(dev, &spi_xfer, 1);
1532bc4d4f8SChristophe Ricard if (r < 0) {
1542bc4d4f8SChristophe Ricard kfree_skb(*skb);
1552bc4d4f8SChristophe Ricard return -EREMOTEIO;
1562bc4d4f8SChristophe Ricard }
1572bc4d4f8SChristophe Ricard
1582bc4d4f8SChristophe Ricard skb_put(*skb, len);
1592bc4d4f8SChristophe Ricard memcpy((*skb)->data + ST_NCI_SPI_MIN_SIZE, buf, len);
1602bc4d4f8SChristophe Ricard
1612bc4d4f8SChristophe Ricard return 0;
1622bc4d4f8SChristophe Ricard }
1632bc4d4f8SChristophe Ricard
1642bc4d4f8SChristophe Ricard /*
1652bc4d4f8SChristophe Ricard * Reads an ndlc frame from the chip.
1662bc4d4f8SChristophe Ricard *
1672bc4d4f8SChristophe Ricard * On ST21NFCB, IRQ goes in idle state when read starts.
1682bc4d4f8SChristophe Ricard */
st_nci_irq_thread_fn(int irq,void * phy_id)1692bc4d4f8SChristophe Ricard static irqreturn_t st_nci_irq_thread_fn(int irq, void *phy_id)
1702bc4d4f8SChristophe Ricard {
1712bc4d4f8SChristophe Ricard struct st_nci_spi_phy *phy = phy_id;
1722bc4d4f8SChristophe Ricard struct sk_buff *skb = NULL;
1732bc4d4f8SChristophe Ricard int r;
1742bc4d4f8SChristophe Ricard
1752bc4d4f8SChristophe Ricard if (!phy || !phy->ndlc || irq != phy->spi_dev->irq) {
1762bc4d4f8SChristophe Ricard WARN_ON_ONCE(1);
1772bc4d4f8SChristophe Ricard return IRQ_NONE;
1782bc4d4f8SChristophe Ricard }
1792bc4d4f8SChristophe Ricard
1802bc4d4f8SChristophe Ricard if (phy->ndlc->hard_fault)
1812bc4d4f8SChristophe Ricard return IRQ_HANDLED;
1822bc4d4f8SChristophe Ricard
1832bc4d4f8SChristophe Ricard if (!phy->ndlc->powered) {
1842bc4d4f8SChristophe Ricard st_nci_spi_disable(phy);
1852bc4d4f8SChristophe Ricard return IRQ_HANDLED;
1862bc4d4f8SChristophe Ricard }
1872bc4d4f8SChristophe Ricard
1882bc4d4f8SChristophe Ricard r = st_nci_spi_read(phy, &skb);
1892bc4d4f8SChristophe Ricard if (r == -EREMOTEIO || r == -ENOMEM || r == -EBADMSG)
1902bc4d4f8SChristophe Ricard return IRQ_HANDLED;
1912bc4d4f8SChristophe Ricard
1922bc4d4f8SChristophe Ricard ndlc_recv(phy->ndlc, skb);
1932bc4d4f8SChristophe Ricard
1942bc4d4f8SChristophe Ricard return IRQ_HANDLED;
1952bc4d4f8SChristophe Ricard }
1962bc4d4f8SChristophe Ricard
1977a5e98daSKrzysztof Kozlowski static const struct nfc_phy_ops spi_phy_ops = {
1982bc4d4f8SChristophe Ricard .write = st_nci_spi_write,
1992bc4d4f8SChristophe Ricard .enable = st_nci_spi_enable,
2002bc4d4f8SChristophe Ricard .disable = st_nci_spi_disable,
2012bc4d4f8SChristophe Ricard };
2022bc4d4f8SChristophe Ricard
20385d23e77SAndy Shevchenko static const struct acpi_gpio_params reset_gpios = { 1, 0, false };
20485d23e77SAndy Shevchenko
20585d23e77SAndy Shevchenko static const struct acpi_gpio_mapping acpi_st_nci_gpios[] = {
20685d23e77SAndy Shevchenko { "reset-gpios", &reset_gpios, 1 },
20785d23e77SAndy Shevchenko {},
20885d23e77SAndy Shevchenko };
20985d23e77SAndy Shevchenko
st_nci_spi_probe(struct spi_device * dev)2102bc4d4f8SChristophe Ricard static int st_nci_spi_probe(struct spi_device *dev)
2112bc4d4f8SChristophe Ricard {
2122bc4d4f8SChristophe Ricard struct st_nci_spi_phy *phy;
2132bc4d4f8SChristophe Ricard int r;
2142bc4d4f8SChristophe Ricard
2152bc4d4f8SChristophe Ricard /* Check SPI platform functionnalities */
2162bc4d4f8SChristophe Ricard if (!dev) {
2172bc4d4f8SChristophe Ricard pr_debug("%s: dev is NULL. Device is not accessible.\n",
2182bc4d4f8SChristophe Ricard __func__);
2192bc4d4f8SChristophe Ricard return -ENODEV;
2202bc4d4f8SChristophe Ricard }
2212bc4d4f8SChristophe Ricard
2222bc4d4f8SChristophe Ricard phy = devm_kzalloc(&dev->dev, sizeof(struct st_nci_spi_phy),
2232bc4d4f8SChristophe Ricard GFP_KERNEL);
2242bc4d4f8SChristophe Ricard if (!phy)
2252bc4d4f8SChristophe Ricard return -ENOMEM;
2262bc4d4f8SChristophe Ricard
2272bc4d4f8SChristophe Ricard phy->spi_dev = dev;
2282bc4d4f8SChristophe Ricard
2292bc4d4f8SChristophe Ricard spi_set_drvdata(dev, phy);
2302bc4d4f8SChristophe Ricard
231c745120eSAndy Shevchenko r = devm_acpi_dev_add_driver_gpios(&dev->dev, acpi_st_nci_gpios);
232c745120eSAndy Shevchenko if (r)
233c745120eSAndy Shevchenko dev_dbg(&dev->dev, "Unable to add GPIO mapping table\n");
234c745120eSAndy Shevchenko
235c745120eSAndy Shevchenko /* Get RESET GPIO */
236c745120eSAndy Shevchenko phy->gpiod_reset = devm_gpiod_get(&dev->dev, "reset", GPIOD_OUT_HIGH);
237c745120eSAndy Shevchenko if (IS_ERR(phy->gpiod_reset)) {
238c745120eSAndy Shevchenko nfc_err(&dev->dev, "Unable to get RESET GPIO\n");
239c745120eSAndy Shevchenko return PTR_ERR(phy->gpiod_reset);
2402bc4d4f8SChristophe Ricard }
2412bc4d4f8SChristophe Ricard
24275719b2bSAndy Shevchenko phy->se_status.is_ese_present =
24375719b2bSAndy Shevchenko device_property_read_bool(&dev->dev, "ese-present");
24475719b2bSAndy Shevchenko phy->se_status.is_uicc_present =
24575719b2bSAndy Shevchenko device_property_read_bool(&dev->dev, "uicc-present");
24675719b2bSAndy Shevchenko
2472bc4d4f8SChristophe Ricard r = ndlc_probe(phy, &spi_phy_ops, &dev->dev,
2482bc4d4f8SChristophe Ricard ST_NCI_FRAME_HEADROOM, ST_NCI_FRAME_TAILROOM,
2493648dc6dSChristophe Ricard &phy->ndlc, &phy->se_status);
2502bc4d4f8SChristophe Ricard if (r < 0) {
2512bc4d4f8SChristophe Ricard nfc_err(&dev->dev, "Unable to register ndlc layer\n");
2522bc4d4f8SChristophe Ricard return r;
2532bc4d4f8SChristophe Ricard }
2542bc4d4f8SChristophe Ricard
255bb2496c3SChristophe Ricard phy->irq_active = true;
2562bc4d4f8SChristophe Ricard r = devm_request_threaded_irq(&dev->dev, dev->irq, NULL,
2572bc4d4f8SChristophe Ricard st_nci_irq_thread_fn,
2581af9fea6SAndy Shevchenko IRQF_ONESHOT,
2592bc4d4f8SChristophe Ricard ST_NCI_SPI_DRIVER_NAME, phy);
2602bc4d4f8SChristophe Ricard if (r < 0)
2612bc4d4f8SChristophe Ricard nfc_err(&dev->dev, "Unable to register IRQ handler\n");
2622bc4d4f8SChristophe Ricard
2632bc4d4f8SChristophe Ricard return r;
2642bc4d4f8SChristophe Ricard }
2652bc4d4f8SChristophe Ricard
st_nci_spi_remove(struct spi_device * dev)266*a0386bbaSUwe Kleine-König static void st_nci_spi_remove(struct spi_device *dev)
2672bc4d4f8SChristophe Ricard {
2682bc4d4f8SChristophe Ricard struct st_nci_spi_phy *phy = spi_get_drvdata(dev);
2692bc4d4f8SChristophe Ricard
2702bc4d4f8SChristophe Ricard ndlc_remove(phy->ndlc);
2712bc4d4f8SChristophe Ricard }
2722bc4d4f8SChristophe Ricard
2733252897fSChristophe Ricard static struct spi_device_id st_nci_spi_id_table[] = {
2743252897fSChristophe Ricard {ST_NCI_SPI_DRIVER_NAME, 0},
27531339440SMark Brown {"st21nfcb-spi", 0},
2763252897fSChristophe Ricard {}
2773252897fSChristophe Ricard };
2783252897fSChristophe Ricard MODULE_DEVICE_TABLE(spi, st_nci_spi_id_table);
2793252897fSChristophe Ricard
280255fcc7bSKrzysztof Kozlowski static const struct acpi_device_id st_nci_spi_acpi_match[] __maybe_unused = {
28160cd6d89SChristophe Ricard {"SMO2101", 0},
28260cd6d89SChristophe Ricard {}
28360cd6d89SChristophe Ricard };
28460cd6d89SChristophe Ricard MODULE_DEVICE_TABLE(acpi, st_nci_spi_acpi_match);
28560cd6d89SChristophe Ricard
286255fcc7bSKrzysztof Kozlowski static const struct of_device_id of_st_nci_spi_match[] __maybe_unused = {
2872bc4d4f8SChristophe Ricard { .compatible = "st,st21nfcb-spi", },
2882bc4d4f8SChristophe Ricard {}
2892bc4d4f8SChristophe Ricard };
2902bc4d4f8SChristophe Ricard MODULE_DEVICE_TABLE(of, of_st_nci_spi_match);
2912bc4d4f8SChristophe Ricard
2922bc4d4f8SChristophe Ricard static struct spi_driver st_nci_spi_driver = {
2932bc4d4f8SChristophe Ricard .driver = {
2942bc4d4f8SChristophe Ricard .name = ST_NCI_SPI_DRIVER_NAME,
2952bc4d4f8SChristophe Ricard .of_match_table = of_match_ptr(of_st_nci_spi_match),
29660cd6d89SChristophe Ricard .acpi_match_table = ACPI_PTR(st_nci_spi_acpi_match),
2972bc4d4f8SChristophe Ricard },
2982bc4d4f8SChristophe Ricard .probe = st_nci_spi_probe,
2992bc4d4f8SChristophe Ricard .id_table = st_nci_spi_id_table,
3002bc4d4f8SChristophe Ricard .remove = st_nci_spi_remove,
3012bc4d4f8SChristophe Ricard };
3022bc4d4f8SChristophe Ricard module_spi_driver(st_nci_spi_driver);
3032bc4d4f8SChristophe Ricard
3042bc4d4f8SChristophe Ricard MODULE_LICENSE("GPL");
3052bc4d4f8SChristophe Ricard MODULE_DESCRIPTION(DRIVER_DESC);
306