aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nfc/nfcmrvl/main.c
diff options
context:
space:
mode:
authorVincent Cuissard <cuissard@marvell.com>2015-10-26 10:27:39 +0100
committerSamuel Ortiz <sameo@linux.intel.com>2015-10-27 04:18:44 +0100
commit3194c6870158e305dac2af52f83681e9cb67280f (patch)
treeb4fc6cbfbd419132051f3a06d67c5d827a5d6e5a /drivers/nfc/nfcmrvl/main.c
parentNFC: NCI: export nci_send_frame and nci_send_cmd function (diff)
downloadlinux-dev-3194c6870158e305dac2af52f83681e9cb67280f.tar.xz
linux-dev-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.c42
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,