Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 18d2c624 authored by Christophe Ricard's avatar Christophe Ricard Committed by Samuel Ortiz
Browse files

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: default avatarChristophe Ricard <christophe-h.ricard@st.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent fcb45e6a
Loading
Loading
Loading
Loading
+39 −8
Original line number Original line Diff line number Diff line
@@ -98,23 +98,49 @@ do { \
		       16, 1, (skb)->data, (skb)->len, 0);	\
		       16, 1, (skb)->data, (skb)->len, 0);	\
} while (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 };
	u16 wait_reboot[] = { 50, 300, 1000 };
	char reboot_cmd[] = { 0x7E, 0x66, 0x48, 0xF6, 0x7E };
	char reboot_cmd[] = { 0x7E, 0x66, 0x48, 0xF6, 0x7E };
	u8 tmp[ST21NFCA_HCI_LLC_MAX_SIZE];
	u8 tmp[ST21NFCA_HCI_LLC_MAX_SIZE];
	int i, r = -1;
	int i, 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));
		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,
		r = i2c_master_recv(phy->i2c_dev, tmp,
				    ST21NFCA_HCI_LLC_MAX_SIZE);
				    ST21NFCA_HCI_LLC_MAX_SIZE);
		if (r < 0)
			msleep(wait_reboot[i]);
	}
	if (r < 0)
		return r;


	r = -1;
	for (i = 0; i < ST21NFCA_HCI_LLC_MAX_SIZE &&
	for (i = 0; i < ARRAY_SIZE(wait_reboot) && r < 0; i++)
		tmp[i] == ST21NFCA_SOF_EOF; i++)
		r = i2c_master_send(phy->i2c_dev, reboot_cmd,
		;
				    sizeof(reboot_cmd));

	usleep_range(1000, 1500);
	if (r != ST21NFCA_HCI_LLC_MAX_SIZE)
		return -ENODEV;


	usleep_range(1000, 1500);
	return 0;
}
}


static int st21nfca_hci_i2c_enable(void *phy_id)
static int st21nfca_hci_i2c_enable(void *phy_id)
@@ -554,7 +580,12 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client,
	}
	}
	client->irq = irq;
	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,
	r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
				st21nfca_hci_irq_thread_fn,
				st21nfca_hci_irq_thread_fn,
				phy->irq_polarity | IRQF_ONESHOT,
				phy->irq_polarity | IRQF_ONESHOT,