summaryrefslogtreecommitdiff
path: root/drivers/nfc/nfcmrvl/main.c
diff options
context:
space:
mode:
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,