diff options
author | Vincent Cuissard <cuissard@marvell.com> | 2015-10-26 10:27:39 +0100 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2015-10-27 04:18:44 +0100 |
commit | 3194c6870158e305dac2af52f83681e9cb67280f (patch) | |
tree | b4fc6cbfbd419132051f3a06d67c5d827a5d6e5a /drivers/nfc/nfcmrvl/main.c | |
parent | NFC: NCI: export nci_send_frame and nci_send_cmd function (diff) | |
download | linux-3194c6870158e305dac2af52f83681e9cb67280f.tar.xz linux-3194c6870158e305dac2af52f83681e9cb67280f.zip |
NFC: nfcmrvl: add firmware download support
Implement firmware download protocol for Marvell NFC controllers.
This protocol is based on NCI frames that's why parts of its
implementation use some NCI generic functions.
Signed-off-by: Vincent Cuissard <cuissard@marvell.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/nfc/nfcmrvl/main.c')
-rw-r--r-- | drivers/nfc/nfcmrvl/main.c | 42 |
1 files changed, 35 insertions, 7 deletions
diff --git a/drivers/nfc/nfcmrvl/main.c b/drivers/nfc/nfcmrvl/main.c index 77e292f45dd8..6fb23cc9a659 100644 --- a/drivers/nfc/nfcmrvl/main.c +++ b/drivers/nfc/nfcmrvl/main.c @@ -61,9 +61,6 @@ static int nfcmrvl_nci_send(struct nci_dev *ndev, struct sk_buff *skb) skb->dev = (void *)ndev; - if (!test_bit(NFCMRVL_NCI_RUNNING, &priv->flags)) - return -EBUSY; - if (priv->config.hci_muxed) { unsigned char *hdr; unsigned char len = skb->len; @@ -86,11 +83,18 @@ static int nfcmrvl_nci_setup(struct nci_dev *ndev) return 0; } +static int nfcmrvl_nci_fw_download(struct nci_dev *ndev, + const char *firmware_name) +{ + return nfcmrvl_fw_dnld_start(ndev, firmware_name); +} + static struct nci_ops nfcmrvl_nci_ops = { .open = nfcmrvl_nci_open, .close = nfcmrvl_nci_close, .send = nfcmrvl_nci_send, .setup = nfcmrvl_nci_setup, + .fw_download = nfcmrvl_nci_fw_download, }; struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data, @@ -143,18 +147,26 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(void *drv_data, nci_set_drvdata(priv->ndev, priv); - nfcmrvl_chip_reset(priv); - rc = nci_register_device(priv->ndev); if (rc) { nfc_err(dev, "nci_register_device failed %d\n", rc); - nci_free_device(priv->ndev); - goto error; + goto error_free_dev; + } + + /* Ensure that controller is powered off */ + nfcmrvl_chip_halt(priv); + + rc = nfcmrvl_fw_dnld_init(priv); + if (rc) { + nfc_err(dev, "failed to initialize FW download %d\n", rc); + goto error_free_dev; } nfc_info(dev, "registered with nci successfully\n"); return priv; +error_free_dev: + nci_free_device(priv->ndev); error: kfree(priv); return ERR_PTR(rc); @@ -165,6 +177,11 @@ void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv) { struct nci_dev *ndev = priv->ndev; + if (priv->ndev->nfc_dev->fw_download_in_progress) + nfcmrvl_fw_dnld_abort(priv); + + nfcmrvl_fw_dnld_deinit(priv); + nci_unregister_device(ndev); nci_free_device(ndev); kfree(priv); @@ -185,6 +202,11 @@ int nfcmrvl_nci_recv_frame(struct nfcmrvl_private *priv, struct sk_buff *skb) } } + if (priv->ndev->nfc_dev->fw_download_in_progress) { + nfcmrvl_fw_dnld_recv_frame(priv, skb); + return 0; + } + if (test_bit(NFCMRVL_NCI_RUNNING, &priv->flags)) nci_recv_frame(priv->ndev, skb); else { @@ -213,6 +235,12 @@ void nfcmrvl_chip_reset(struct nfcmrvl_private *priv) nfc_info(priv->dev, "no reset available on this interface\n"); } +void nfcmrvl_chip_halt(struct nfcmrvl_private *priv) +{ + if (priv->config.reset_n_io) + gpio_set_value(priv->config.reset_n_io, 0); +} + #ifdef CONFIG_OF int nfcmrvl_parse_dt(struct device_node *node, |