NFC: st21nfca: Improve st21nfca initialization by handling reboot properly

Change in st21nfca_hci_platform_init in order to handle in a better way the
internal reboot command.
Once the reboot is completed, the driver expect to receive a 0x7e filled
buffer.

Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c
index 4cbd8fb..6c4d0a0 100644
--- a/drivers/nfc/st21nfca/i2c.c
+++ b/drivers/nfc/st21nfca/i2c.c
@@ -98,23 +98,49 @@
 		       16, 1, (skb)->data, (skb)->len, 0);	\
 } while (0)
 
-static void st21nfca_hci_platform_init(struct st21nfca_i2c_phy *phy)
+/*
+ * In order to get the CLF in a known state we generate an internal reboot
+ * using a proprietary command.
+ * Once the reboot is completed, we expect to receive a ST21NFCA_SOF_EOF
+ * fill buffer.
+ */
+static int st21nfca_hci_platform_init(struct st21nfca_i2c_phy *phy)
 {
 	u16 wait_reboot[] = { 50, 300, 1000 };
 	char reboot_cmd[] = { 0x7E, 0x66, 0x48, 0xF6, 0x7E };
 	u8 tmp[ST21NFCA_HCI_LLC_MAX_SIZE];
 	int i, r = -1;
 
-	for (i = 0; i < ARRAY_SIZE(wait_reboot) && r < 0; i++)
-		r = i2c_master_recv(phy->i2c_dev, tmp,
-				    ST21NFCA_HCI_LLC_MAX_SIZE);
-
-	r = -1;
-	for (i = 0; i < ARRAY_SIZE(wait_reboot) && r < 0; i++)
+	for (i = 0; i < ARRAY_SIZE(wait_reboot) && r < 0; i++) {
 		r = i2c_master_send(phy->i2c_dev, reboot_cmd,
 				    sizeof(reboot_cmd));
-	usleep_range(1000, 1500);
+		if (r < 0)
+			msleep(wait_reboot[i]);
+	}
+	if (r < 0)
+		return r;
 
+	/* CLF is spending about 20ms to do an internal reboot */
+	msleep(20);
+	r = -1;
+	for (i = 0; i < ARRAY_SIZE(wait_reboot) && r < 0; i++) {
+		r = i2c_master_recv(phy->i2c_dev, tmp,
+				    ST21NFCA_HCI_LLC_MAX_SIZE);
+		if (r < 0)
+			msleep(wait_reboot[i]);
+	}
+	if (r < 0)
+		return r;
+
+	for (i = 0; i < ST21NFCA_HCI_LLC_MAX_SIZE &&
+		tmp[i] == ST21NFCA_SOF_EOF; i++)
+		;
+
+	if (r != ST21NFCA_HCI_LLC_MAX_SIZE)
+		return -ENODEV;
+
+	usleep_range(1000, 1500);
+	return 0;
 }
 
 static int st21nfca_hci_i2c_enable(void *phy_id)
@@ -554,7 +580,12 @@
 	}
 	client->irq = irq;
 
-	st21nfca_hci_platform_init(phy);
+	r = st21nfca_hci_platform_init(phy);
+	if (r < 0) {
+		nfc_err(&client->dev, "Unable to reboot st21nfca\n");
+		return -ENODEV;
+	}
+
 	r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
 				st21nfca_hci_irq_thread_fn,
 				phy->irq_polarity | IRQF_ONESHOT,