18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * I2C Link Layer for ST NCI NFC controller familly based Driver
48c2ecf20Sopenharmony_ci * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/module.h>
108c2ecf20Sopenharmony_ci#include <linux/i2c.h>
118c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h>
128c2ecf20Sopenharmony_ci#include <linux/acpi.h>
138c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
148c2ecf20Sopenharmony_ci#include <linux/delay.h>
158c2ecf20Sopenharmony_ci#include <linux/nfc.h>
168c2ecf20Sopenharmony_ci#include <linux/of.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include "st-nci.h"
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#define DRIVER_DESC "NCI NFC driver for ST_NCI"
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/* ndlc header */
238c2ecf20Sopenharmony_ci#define ST_NCI_FRAME_HEADROOM 1
248c2ecf20Sopenharmony_ci#define ST_NCI_FRAME_TAILROOM 0
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#define ST_NCI_I2C_MIN_SIZE 4   /* PCB(1) + NCI Packet header(3) */
278c2ecf20Sopenharmony_ci#define ST_NCI_I2C_MAX_SIZE 250 /* req 4.2.1 */
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#define ST_NCI_DRIVER_NAME "st_nci"
308c2ecf20Sopenharmony_ci#define ST_NCI_I2C_DRIVER_NAME "st_nci_i2c"
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistruct st_nci_i2c_phy {
338c2ecf20Sopenharmony_ci	struct i2c_client *i2c_dev;
348c2ecf20Sopenharmony_ci	struct llt_ndlc *ndlc;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	bool irq_active;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	struct gpio_desc *gpiod_reset;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	struct st_nci_se_status se_status;
418c2ecf20Sopenharmony_ci};
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cistatic int st_nci_i2c_enable(void *phy_id)
448c2ecf20Sopenharmony_ci{
458c2ecf20Sopenharmony_ci	struct st_nci_i2c_phy *phy = phy_id;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	gpiod_set_value(phy->gpiod_reset, 0);
488c2ecf20Sopenharmony_ci	usleep_range(10000, 15000);
498c2ecf20Sopenharmony_ci	gpiod_set_value(phy->gpiod_reset, 1);
508c2ecf20Sopenharmony_ci	usleep_range(80000, 85000);
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci	if (phy->ndlc->powered == 0 && phy->irq_active == 0) {
538c2ecf20Sopenharmony_ci		enable_irq(phy->i2c_dev->irq);
548c2ecf20Sopenharmony_ci		phy->irq_active = true;
558c2ecf20Sopenharmony_ci	}
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	return 0;
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cistatic void st_nci_i2c_disable(void *phy_id)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	struct st_nci_i2c_phy *phy = phy_id;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	disable_irq_nosync(phy->i2c_dev->irq);
658c2ecf20Sopenharmony_ci	phy->irq_active = false;
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci/*
698c2ecf20Sopenharmony_ci * Writing a frame must not return the number of written bytes.
708c2ecf20Sopenharmony_ci * It must return either zero for success, or <0 for error.
718c2ecf20Sopenharmony_ci * In addition, it must not alter the skb
728c2ecf20Sopenharmony_ci */
738c2ecf20Sopenharmony_cistatic int st_nci_i2c_write(void *phy_id, struct sk_buff *skb)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	int r;
768c2ecf20Sopenharmony_ci	struct st_nci_i2c_phy *phy = phy_id;
778c2ecf20Sopenharmony_ci	struct i2c_client *client = phy->i2c_dev;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	if (phy->ndlc->hard_fault != 0)
808c2ecf20Sopenharmony_ci		return phy->ndlc->hard_fault;
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	r = i2c_master_send(client, skb->data, skb->len);
838c2ecf20Sopenharmony_ci	if (r < 0) {  /* Retry, chip was in standby */
848c2ecf20Sopenharmony_ci		usleep_range(1000, 4000);
858c2ecf20Sopenharmony_ci		r = i2c_master_send(client, skb->data, skb->len);
868c2ecf20Sopenharmony_ci	}
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	if (r >= 0) {
898c2ecf20Sopenharmony_ci		if (r != skb->len)
908c2ecf20Sopenharmony_ci			r = -EREMOTEIO;
918c2ecf20Sopenharmony_ci		else
928c2ecf20Sopenharmony_ci			r = 0;
938c2ecf20Sopenharmony_ci	}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	return r;
968c2ecf20Sopenharmony_ci}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci/*
998c2ecf20Sopenharmony_ci * Reads an ndlc frame and returns it in a newly allocated sk_buff.
1008c2ecf20Sopenharmony_ci * returns:
1018c2ecf20Sopenharmony_ci * 0 : if received frame is complete
1028c2ecf20Sopenharmony_ci * -EREMOTEIO : i2c read error (fatal)
1038c2ecf20Sopenharmony_ci * -EBADMSG : frame was incorrect and discarded
1048c2ecf20Sopenharmony_ci * -ENOMEM : cannot allocate skb, frame dropped
1058c2ecf20Sopenharmony_ci */
1068c2ecf20Sopenharmony_cistatic int st_nci_i2c_read(struct st_nci_i2c_phy *phy,
1078c2ecf20Sopenharmony_ci				 struct sk_buff **skb)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	int r;
1108c2ecf20Sopenharmony_ci	u8 len;
1118c2ecf20Sopenharmony_ci	u8 buf[ST_NCI_I2C_MAX_SIZE];
1128c2ecf20Sopenharmony_ci	struct i2c_client *client = phy->i2c_dev;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	r = i2c_master_recv(client, buf, ST_NCI_I2C_MIN_SIZE);
1158c2ecf20Sopenharmony_ci	if (r < 0) {  /* Retry, chip was in standby */
1168c2ecf20Sopenharmony_ci		usleep_range(1000, 4000);
1178c2ecf20Sopenharmony_ci		r = i2c_master_recv(client, buf, ST_NCI_I2C_MIN_SIZE);
1188c2ecf20Sopenharmony_ci	}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	if (r != ST_NCI_I2C_MIN_SIZE)
1218c2ecf20Sopenharmony_ci		return -EREMOTEIO;
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	len = be16_to_cpu(*(__be16 *) (buf + 2));
1248c2ecf20Sopenharmony_ci	if (len > ST_NCI_I2C_MAX_SIZE) {
1258c2ecf20Sopenharmony_ci		nfc_err(&client->dev, "invalid frame len\n");
1268c2ecf20Sopenharmony_ci		return -EBADMSG;
1278c2ecf20Sopenharmony_ci	}
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	*skb = alloc_skb(ST_NCI_I2C_MIN_SIZE + len, GFP_KERNEL);
1308c2ecf20Sopenharmony_ci	if (*skb == NULL)
1318c2ecf20Sopenharmony_ci		return -ENOMEM;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	skb_reserve(*skb, ST_NCI_I2C_MIN_SIZE);
1348c2ecf20Sopenharmony_ci	skb_put(*skb, ST_NCI_I2C_MIN_SIZE);
1358c2ecf20Sopenharmony_ci	memcpy((*skb)->data, buf, ST_NCI_I2C_MIN_SIZE);
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	if (!len)
1388c2ecf20Sopenharmony_ci		return 0;
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	r = i2c_master_recv(client, buf, len);
1418c2ecf20Sopenharmony_ci	if (r != len) {
1428c2ecf20Sopenharmony_ci		kfree_skb(*skb);
1438c2ecf20Sopenharmony_ci		return -EREMOTEIO;
1448c2ecf20Sopenharmony_ci	}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	skb_put(*skb, len);
1478c2ecf20Sopenharmony_ci	memcpy((*skb)->data + ST_NCI_I2C_MIN_SIZE, buf, len);
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	return 0;
1508c2ecf20Sopenharmony_ci}
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci/*
1538c2ecf20Sopenharmony_ci * Reads an ndlc frame from the chip.
1548c2ecf20Sopenharmony_ci *
1558c2ecf20Sopenharmony_ci * On ST_NCI, IRQ goes in idle state when read starts.
1568c2ecf20Sopenharmony_ci */
1578c2ecf20Sopenharmony_cistatic irqreturn_t st_nci_irq_thread_fn(int irq, void *phy_id)
1588c2ecf20Sopenharmony_ci{
1598c2ecf20Sopenharmony_ci	struct st_nci_i2c_phy *phy = phy_id;
1608c2ecf20Sopenharmony_ci	struct i2c_client *client;
1618c2ecf20Sopenharmony_ci	struct sk_buff *skb = NULL;
1628c2ecf20Sopenharmony_ci	int r;
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	if (!phy || !phy->ndlc || irq != phy->i2c_dev->irq) {
1658c2ecf20Sopenharmony_ci		WARN_ON_ONCE(1);
1668c2ecf20Sopenharmony_ci		return IRQ_NONE;
1678c2ecf20Sopenharmony_ci	}
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	client = phy->i2c_dev;
1708c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "IRQ\n");
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	if (phy->ndlc->hard_fault)
1738c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	if (!phy->ndlc->powered) {
1768c2ecf20Sopenharmony_ci		st_nci_i2c_disable(phy);
1778c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
1788c2ecf20Sopenharmony_ci	}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	r = st_nci_i2c_read(phy, &skb);
1818c2ecf20Sopenharmony_ci	if (r == -EREMOTEIO || r == -ENOMEM || r == -EBADMSG)
1828c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	ndlc_recv(phy->ndlc, skb);
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
1878c2ecf20Sopenharmony_ci}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_cistatic struct nfc_phy_ops i2c_phy_ops = {
1908c2ecf20Sopenharmony_ci	.write = st_nci_i2c_write,
1918c2ecf20Sopenharmony_ci	.enable = st_nci_i2c_enable,
1928c2ecf20Sopenharmony_ci	.disable = st_nci_i2c_disable,
1938c2ecf20Sopenharmony_ci};
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_cistatic const struct acpi_gpio_params reset_gpios = { 1, 0, false };
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_cistatic const struct acpi_gpio_mapping acpi_st_nci_gpios[] = {
1988c2ecf20Sopenharmony_ci	{ "reset-gpios", &reset_gpios, 1 },
1998c2ecf20Sopenharmony_ci	{},
2008c2ecf20Sopenharmony_ci};
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_cistatic int st_nci_i2c_probe(struct i2c_client *client,
2038c2ecf20Sopenharmony_ci				  const struct i2c_device_id *id)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	struct device *dev = &client->dev;
2068c2ecf20Sopenharmony_ci	struct st_nci_i2c_phy *phy;
2078c2ecf20Sopenharmony_ci	int r;
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "%s\n", __func__);
2108c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "IRQ: %d\n", client->irq);
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
2138c2ecf20Sopenharmony_ci		nfc_err(&client->dev, "Need I2C_FUNC_I2C\n");
2148c2ecf20Sopenharmony_ci		return -ENODEV;
2158c2ecf20Sopenharmony_ci	}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	phy = devm_kzalloc(dev, sizeof(struct st_nci_i2c_phy), GFP_KERNEL);
2188c2ecf20Sopenharmony_ci	if (!phy)
2198c2ecf20Sopenharmony_ci		return -ENOMEM;
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	phy->i2c_dev = client;
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	i2c_set_clientdata(client, phy);
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	r = devm_acpi_dev_add_driver_gpios(dev, acpi_st_nci_gpios);
2268c2ecf20Sopenharmony_ci	if (r)
2278c2ecf20Sopenharmony_ci		dev_dbg(dev, "Unable to add GPIO mapping table\n");
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	/* Get RESET GPIO */
2308c2ecf20Sopenharmony_ci	phy->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
2318c2ecf20Sopenharmony_ci	if (IS_ERR(phy->gpiod_reset)) {
2328c2ecf20Sopenharmony_ci		nfc_err(dev, "Unable to get RESET GPIO\n");
2338c2ecf20Sopenharmony_ci		return -ENODEV;
2348c2ecf20Sopenharmony_ci	}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	phy->se_status.is_ese_present =
2378c2ecf20Sopenharmony_ci				device_property_read_bool(dev, "ese-present");
2388c2ecf20Sopenharmony_ci	phy->se_status.is_uicc_present =
2398c2ecf20Sopenharmony_ci				device_property_read_bool(dev, "uicc-present");
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	r = ndlc_probe(phy, &i2c_phy_ops, &client->dev,
2428c2ecf20Sopenharmony_ci			ST_NCI_FRAME_HEADROOM, ST_NCI_FRAME_TAILROOM,
2438c2ecf20Sopenharmony_ci			&phy->ndlc, &phy->se_status);
2448c2ecf20Sopenharmony_ci	if (r < 0) {
2458c2ecf20Sopenharmony_ci		nfc_err(&client->dev, "Unable to register ndlc layer\n");
2468c2ecf20Sopenharmony_ci		return r;
2478c2ecf20Sopenharmony_ci	}
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	phy->irq_active = true;
2508c2ecf20Sopenharmony_ci	r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
2518c2ecf20Sopenharmony_ci				st_nci_irq_thread_fn,
2528c2ecf20Sopenharmony_ci				IRQF_ONESHOT,
2538c2ecf20Sopenharmony_ci				ST_NCI_DRIVER_NAME, phy);
2548c2ecf20Sopenharmony_ci	if (r < 0)
2558c2ecf20Sopenharmony_ci		nfc_err(&client->dev, "Unable to register IRQ handler\n");
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	return r;
2588c2ecf20Sopenharmony_ci}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_cistatic int st_nci_i2c_remove(struct i2c_client *client)
2618c2ecf20Sopenharmony_ci{
2628c2ecf20Sopenharmony_ci	struct st_nci_i2c_phy *phy = i2c_get_clientdata(client);
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	dev_dbg(&client->dev, "%s\n", __func__);
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	ndlc_remove(phy->ndlc);
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	return 0;
2698c2ecf20Sopenharmony_ci}
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_cistatic const struct i2c_device_id st_nci_i2c_id_table[] = {
2728c2ecf20Sopenharmony_ci	{ST_NCI_DRIVER_NAME, 0},
2738c2ecf20Sopenharmony_ci	{}
2748c2ecf20Sopenharmony_ci};
2758c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, st_nci_i2c_id_table);
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_cistatic const struct acpi_device_id st_nci_i2c_acpi_match[] = {
2788c2ecf20Sopenharmony_ci	{"SMO2101"},
2798c2ecf20Sopenharmony_ci	{"SMO2102"},
2808c2ecf20Sopenharmony_ci	{}
2818c2ecf20Sopenharmony_ci};
2828c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, st_nci_i2c_acpi_match);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_cistatic const struct of_device_id of_st_nci_i2c_match[] = {
2858c2ecf20Sopenharmony_ci	{ .compatible = "st,st21nfcb-i2c", },
2868c2ecf20Sopenharmony_ci	{ .compatible = "st,st21nfcb_i2c", },
2878c2ecf20Sopenharmony_ci	{ .compatible = "st,st21nfcc-i2c", },
2888c2ecf20Sopenharmony_ci	{}
2898c2ecf20Sopenharmony_ci};
2908c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, of_st_nci_i2c_match);
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_cistatic struct i2c_driver st_nci_i2c_driver = {
2938c2ecf20Sopenharmony_ci	.driver = {
2948c2ecf20Sopenharmony_ci		.name = ST_NCI_I2C_DRIVER_NAME,
2958c2ecf20Sopenharmony_ci		.of_match_table = of_match_ptr(of_st_nci_i2c_match),
2968c2ecf20Sopenharmony_ci		.acpi_match_table = ACPI_PTR(st_nci_i2c_acpi_match),
2978c2ecf20Sopenharmony_ci	},
2988c2ecf20Sopenharmony_ci	.probe = st_nci_i2c_probe,
2998c2ecf20Sopenharmony_ci	.id_table = st_nci_i2c_id_table,
3008c2ecf20Sopenharmony_ci	.remove = st_nci_i2c_remove,
3018c2ecf20Sopenharmony_ci};
3028c2ecf20Sopenharmony_cimodule_i2c_driver(st_nci_i2c_driver);
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
3058c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC);
306