linux/drivers/nfc/nfcmrvl/i2c.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Marvell NFC-over-I2C driver: I2C interface related functions
   4 *
   5 * Copyright (C) 2015, Marvell International Ltd.
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/interrupt.h>
  10#include <linux/i2c.h>
  11#include <linux/nfc.h>
  12#include <linux/delay.h>
  13#include <linux/of_irq.h>
  14#include <net/nfc/nci.h>
  15#include <net/nfc/nci_core.h>
  16#include "nfcmrvl.h"
  17
  18struct nfcmrvl_i2c_drv_data {
  19        unsigned long flags;
  20        struct device *dev;
  21        struct i2c_client *i2c;
  22        struct nfcmrvl_private *priv;
  23};
  24
  25static int nfcmrvl_i2c_read(struct nfcmrvl_i2c_drv_data *drv_data,
  26                            struct sk_buff **skb)
  27{
  28        int ret;
  29        struct nci_ctrl_hdr nci_hdr;
  30
  31        /* Read NCI header to know the payload size */
  32        ret = i2c_master_recv(drv_data->i2c, (u8 *)&nci_hdr, NCI_CTRL_HDR_SIZE);
  33        if (ret != NCI_CTRL_HDR_SIZE) {
  34                nfc_err(&drv_data->i2c->dev, "cannot read NCI header\n");
  35                return -EBADMSG;
  36        }
  37
  38        *skb = nci_skb_alloc(drv_data->priv->ndev,
  39                             nci_hdr.plen + NCI_CTRL_HDR_SIZE, GFP_KERNEL);
  40        if (!*skb)
  41                return -ENOMEM;
  42
  43        /* Copy NCI header into the SKB */
  44        skb_put_data(*skb, &nci_hdr, NCI_CTRL_HDR_SIZE);
  45
  46        if (nci_hdr.plen) {
  47                /* Read the NCI payload */
  48                ret = i2c_master_recv(drv_data->i2c,
  49                                      skb_put(*skb, nci_hdr.plen),
  50                                      nci_hdr.plen);
  51
  52                if (ret != nci_hdr.plen) {
  53                        nfc_err(&drv_data->i2c->dev,
  54                                "Invalid frame payload length: %u (expected %u)\n",
  55                                ret, nci_hdr.plen);
  56                        kfree_skb(*skb);
  57                        return -EBADMSG;
  58                }
  59        }
  60
  61        return 0;
  62}
  63
  64static irqreturn_t nfcmrvl_i2c_int_irq_thread_fn(int irq, void *drv_data_ptr)
  65{
  66        struct nfcmrvl_i2c_drv_data *drv_data = drv_data_ptr;
  67        struct sk_buff *skb = NULL;
  68        int ret;
  69
  70        if (!drv_data->priv)
  71                return IRQ_HANDLED;
  72
  73        if (test_bit(NFCMRVL_PHY_ERROR, &drv_data->priv->flags))
  74                return IRQ_HANDLED;
  75
  76        ret = nfcmrvl_i2c_read(drv_data, &skb);
  77
  78        switch (ret) {
  79        case -EREMOTEIO:
  80                set_bit(NFCMRVL_PHY_ERROR, &drv_data->priv->flags);
  81                break;
  82        case -ENOMEM:
  83        case -EBADMSG:
  84                nfc_err(&drv_data->i2c->dev, "read failed %d\n", ret);
  85                break;
  86        default:
  87                if (nfcmrvl_nci_recv_frame(drv_data->priv, skb) < 0)
  88                        nfc_err(&drv_data->i2c->dev, "corrupted RX packet\n");
  89                break;
  90        }
  91        return IRQ_HANDLED;
  92}
  93
  94static int nfcmrvl_i2c_nci_open(struct nfcmrvl_private *priv)
  95{
  96        struct nfcmrvl_i2c_drv_data *drv_data = priv->drv_data;
  97
  98        if (!drv_data)
  99                return -ENODEV;
 100
 101        return 0;
 102}
 103
 104static int nfcmrvl_i2c_nci_close(struct nfcmrvl_private *priv)
 105{
 106        return 0;
 107}
 108
 109static int nfcmrvl_i2c_nci_send(struct nfcmrvl_private *priv,
 110                                struct sk_buff *skb)
 111{
 112        struct nfcmrvl_i2c_drv_data *drv_data = priv->drv_data;
 113        int ret;
 114
 115        if (test_bit(NFCMRVL_PHY_ERROR, &priv->flags))
 116                return -EREMOTEIO;
 117
 118        ret = i2c_master_send(drv_data->i2c, skb->data, skb->len);
 119
 120        /* Retry if chip was in standby */
 121        if (ret == -EREMOTEIO) {
 122                nfc_info(drv_data->dev, "chip may sleep, retry\n");
 123                usleep_range(6000, 10000);
 124                ret = i2c_master_send(drv_data->i2c, skb->data, skb->len);
 125        }
 126
 127        if (ret >= 0) {
 128                if (ret != skb->len) {
 129                        nfc_err(drv_data->dev,
 130                                "Invalid length sent: %u (expected %u)\n",
 131                                ret, skb->len);
 132                        ret = -EREMOTEIO;
 133                } else
 134                        ret = 0;
 135                kfree_skb(skb);
 136        }
 137
 138        return ret;
 139}
 140
 141static void nfcmrvl_i2c_nci_update_config(struct nfcmrvl_private *priv,
 142                                          const void *param)
 143{
 144}
 145
 146static const struct nfcmrvl_if_ops i2c_ops = {
 147        .nci_open = nfcmrvl_i2c_nci_open,
 148        .nci_close = nfcmrvl_i2c_nci_close,
 149        .nci_send = nfcmrvl_i2c_nci_send,
 150        .nci_update_config = nfcmrvl_i2c_nci_update_config,
 151};
 152
 153static int nfcmrvl_i2c_parse_dt(struct device_node *node,
 154                                struct nfcmrvl_platform_data *pdata)
 155{
 156        int ret;
 157
 158        ret = nfcmrvl_parse_dt(node, pdata);
 159        if (ret < 0) {
 160                pr_err("Failed to get generic entries\n");
 161                return ret;
 162        }
 163
 164        if (of_find_property(node, "i2c-int-falling", NULL))
 165                pdata->irq_polarity = IRQF_TRIGGER_FALLING;
 166        else
 167                pdata->irq_polarity = IRQF_TRIGGER_RISING;
 168
 169        ret = irq_of_parse_and_map(node, 0);
 170        if (ret < 0) {
 171                pr_err("Unable to get irq, error: %d\n", ret);
 172                return ret;
 173        }
 174        pdata->irq = ret;
 175
 176        return 0;
 177}
 178
 179static int nfcmrvl_i2c_probe(struct i2c_client *client,
 180                             const struct i2c_device_id *id)
 181{
 182        const struct nfcmrvl_platform_data *pdata;
 183        struct nfcmrvl_i2c_drv_data *drv_data;
 184        struct nfcmrvl_platform_data config;
 185        int ret;
 186
 187        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 188                nfc_err(&client->dev, "Need I2C_FUNC_I2C\n");
 189                return -ENODEV;
 190        }
 191
 192        drv_data = devm_kzalloc(&client->dev, sizeof(*drv_data), GFP_KERNEL);
 193        if (!drv_data)
 194                return -ENOMEM;
 195
 196        drv_data->i2c = client;
 197        drv_data->dev = &client->dev;
 198        drv_data->priv = NULL;
 199
 200        i2c_set_clientdata(client, drv_data);
 201
 202        pdata = client->dev.platform_data;
 203
 204        if (!pdata && client->dev.of_node)
 205                if (nfcmrvl_i2c_parse_dt(client->dev.of_node, &config) == 0)
 206                        pdata = &config;
 207
 208        if (!pdata)
 209                return -EINVAL;
 210
 211        /* Request the read IRQ */
 212        ret = devm_request_threaded_irq(&drv_data->i2c->dev, pdata->irq,
 213                                        NULL, nfcmrvl_i2c_int_irq_thread_fn,
 214                                        pdata->irq_polarity | IRQF_ONESHOT,
 215                                        "nfcmrvl_i2c_int", drv_data);
 216        if (ret < 0) {
 217                nfc_err(&drv_data->i2c->dev,
 218                        "Unable to register IRQ handler\n");
 219                return ret;
 220        }
 221
 222        drv_data->priv = nfcmrvl_nci_register_dev(NFCMRVL_PHY_I2C,
 223                                                  drv_data, &i2c_ops,
 224                                                  &drv_data->i2c->dev, pdata);
 225
 226        if (IS_ERR(drv_data->priv))
 227                return PTR_ERR(drv_data->priv);
 228
 229        drv_data->priv->support_fw_dnld = true;
 230
 231        return 0;
 232}
 233
 234static int nfcmrvl_i2c_remove(struct i2c_client *client)
 235{
 236        struct nfcmrvl_i2c_drv_data *drv_data = i2c_get_clientdata(client);
 237
 238        nfcmrvl_nci_unregister_dev(drv_data->priv);
 239
 240        return 0;
 241}
 242
 243
 244static const struct of_device_id of_nfcmrvl_i2c_match[] __maybe_unused = {
 245        { .compatible = "marvell,nfc-i2c", },
 246        {},
 247};
 248MODULE_DEVICE_TABLE(of, of_nfcmrvl_i2c_match);
 249
 250static const struct i2c_device_id nfcmrvl_i2c_id_table[] = {
 251        { "nfcmrvl_i2c", 0 },
 252        {}
 253};
 254MODULE_DEVICE_TABLE(i2c, nfcmrvl_i2c_id_table);
 255
 256static struct i2c_driver nfcmrvl_i2c_driver = {
 257        .probe = nfcmrvl_i2c_probe,
 258        .id_table = nfcmrvl_i2c_id_table,
 259        .remove = nfcmrvl_i2c_remove,
 260        .driver = {
 261                .name           = "nfcmrvl_i2c",
 262                .of_match_table = of_match_ptr(of_nfcmrvl_i2c_match),
 263        },
 264};
 265
 266module_i2c_driver(nfcmrvl_i2c_driver);
 267
 268MODULE_AUTHOR("Marvell International Ltd.");
 269MODULE_DESCRIPTION("Marvell NFC-over-I2C driver");
 270MODULE_LICENSE("GPL v2");
 271