162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * I2C Link Layer for ST NCI NFC controller familly based Driver
462306a36Sopenharmony_ci * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/module.h>
1062306a36Sopenharmony_ci#include <linux/i2c.h>
1162306a36Sopenharmony_ci#include <linux/gpio/consumer.h>
1262306a36Sopenharmony_ci#include <linux/acpi.h>
1362306a36Sopenharmony_ci#include <linux/interrupt.h>
1462306a36Sopenharmony_ci#include <linux/delay.h>
1562306a36Sopenharmony_ci#include <linux/nfc.h>
1662306a36Sopenharmony_ci#include <linux/of.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include "st-nci.h"
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#define DRIVER_DESC "NCI NFC driver for ST_NCI"
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/* ndlc header */
2362306a36Sopenharmony_ci#define ST_NCI_FRAME_HEADROOM 1
2462306a36Sopenharmony_ci#define ST_NCI_FRAME_TAILROOM 0
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define ST_NCI_I2C_MIN_SIZE 4   /* PCB(1) + NCI Packet header(3) */
2762306a36Sopenharmony_ci#define ST_NCI_I2C_MAX_SIZE 250 /* req 4.2.1 */
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#define ST_NCI_DRIVER_NAME "st_nci"
3062306a36Sopenharmony_ci#define ST_NCI_I2C_DRIVER_NAME "st_nci_i2c"
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistruct st_nci_i2c_phy {
3362306a36Sopenharmony_ci	struct i2c_client *i2c_dev;
3462306a36Sopenharmony_ci	struct llt_ndlc *ndlc;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	bool irq_active;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	struct gpio_desc *gpiod_reset;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	struct st_nci_se_status se_status;
4162306a36Sopenharmony_ci};
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistatic int st_nci_i2c_enable(void *phy_id)
4462306a36Sopenharmony_ci{
4562306a36Sopenharmony_ci	struct st_nci_i2c_phy *phy = phy_id;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	gpiod_set_value(phy->gpiod_reset, 0);
4862306a36Sopenharmony_ci	usleep_range(10000, 15000);
4962306a36Sopenharmony_ci	gpiod_set_value(phy->gpiod_reset, 1);
5062306a36Sopenharmony_ci	usleep_range(80000, 85000);
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	if (phy->ndlc->powered == 0 && phy->irq_active == 0) {
5362306a36Sopenharmony_ci		enable_irq(phy->i2c_dev->irq);
5462306a36Sopenharmony_ci		phy->irq_active = true;
5562306a36Sopenharmony_ci	}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	return 0;
5862306a36Sopenharmony_ci}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistatic void st_nci_i2c_disable(void *phy_id)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	struct st_nci_i2c_phy *phy = phy_id;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	disable_irq_nosync(phy->i2c_dev->irq);
6562306a36Sopenharmony_ci	phy->irq_active = false;
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/*
6962306a36Sopenharmony_ci * Writing a frame must not return the number of written bytes.
7062306a36Sopenharmony_ci * It must return either zero for success, or <0 for error.
7162306a36Sopenharmony_ci * In addition, it must not alter the skb
7262306a36Sopenharmony_ci */
7362306a36Sopenharmony_cistatic int st_nci_i2c_write(void *phy_id, struct sk_buff *skb)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	int r;
7662306a36Sopenharmony_ci	struct st_nci_i2c_phy *phy = phy_id;
7762306a36Sopenharmony_ci	struct i2c_client *client = phy->i2c_dev;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	if (phy->ndlc->hard_fault != 0)
8062306a36Sopenharmony_ci		return phy->ndlc->hard_fault;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	r = i2c_master_send(client, skb->data, skb->len);
8362306a36Sopenharmony_ci	if (r < 0) {  /* Retry, chip was in standby */
8462306a36Sopenharmony_ci		usleep_range(1000, 4000);
8562306a36Sopenharmony_ci		r = i2c_master_send(client, skb->data, skb->len);
8662306a36Sopenharmony_ci	}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	if (r >= 0) {
8962306a36Sopenharmony_ci		if (r != skb->len)
9062306a36Sopenharmony_ci			r = -EREMOTEIO;
9162306a36Sopenharmony_ci		else
9262306a36Sopenharmony_ci			r = 0;
9362306a36Sopenharmony_ci	}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	return r;
9662306a36Sopenharmony_ci}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci/*
9962306a36Sopenharmony_ci * Reads an ndlc frame and returns it in a newly allocated sk_buff.
10062306a36Sopenharmony_ci * returns:
10162306a36Sopenharmony_ci * 0 : if received frame is complete
10262306a36Sopenharmony_ci * -EREMOTEIO : i2c read error (fatal)
10362306a36Sopenharmony_ci * -EBADMSG : frame was incorrect and discarded
10462306a36Sopenharmony_ci * -ENOMEM : cannot allocate skb, frame dropped
10562306a36Sopenharmony_ci */
10662306a36Sopenharmony_cistatic int st_nci_i2c_read(struct st_nci_i2c_phy *phy,
10762306a36Sopenharmony_ci				 struct sk_buff **skb)
10862306a36Sopenharmony_ci{
10962306a36Sopenharmony_ci	int r;
11062306a36Sopenharmony_ci	u8 len;
11162306a36Sopenharmony_ci	u8 buf[ST_NCI_I2C_MAX_SIZE];
11262306a36Sopenharmony_ci	struct i2c_client *client = phy->i2c_dev;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	r = i2c_master_recv(client, buf, ST_NCI_I2C_MIN_SIZE);
11562306a36Sopenharmony_ci	if (r < 0) {  /* Retry, chip was in standby */
11662306a36Sopenharmony_ci		usleep_range(1000, 4000);
11762306a36Sopenharmony_ci		r = i2c_master_recv(client, buf, ST_NCI_I2C_MIN_SIZE);
11862306a36Sopenharmony_ci	}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	if (r != ST_NCI_I2C_MIN_SIZE)
12162306a36Sopenharmony_ci		return -EREMOTEIO;
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	len = be16_to_cpu(*(__be16 *) (buf + 2));
12462306a36Sopenharmony_ci	if (len > ST_NCI_I2C_MAX_SIZE) {
12562306a36Sopenharmony_ci		nfc_err(&client->dev, "invalid frame len\n");
12662306a36Sopenharmony_ci		return -EBADMSG;
12762306a36Sopenharmony_ci	}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	*skb = alloc_skb(ST_NCI_I2C_MIN_SIZE + len, GFP_KERNEL);
13062306a36Sopenharmony_ci	if (*skb == NULL)
13162306a36Sopenharmony_ci		return -ENOMEM;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	skb_reserve(*skb, ST_NCI_I2C_MIN_SIZE);
13462306a36Sopenharmony_ci	skb_put(*skb, ST_NCI_I2C_MIN_SIZE);
13562306a36Sopenharmony_ci	memcpy((*skb)->data, buf, ST_NCI_I2C_MIN_SIZE);
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	if (!len)
13862306a36Sopenharmony_ci		return 0;
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	r = i2c_master_recv(client, buf, len);
14162306a36Sopenharmony_ci	if (r != len) {
14262306a36Sopenharmony_ci		kfree_skb(*skb);
14362306a36Sopenharmony_ci		return -EREMOTEIO;
14462306a36Sopenharmony_ci	}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	skb_put(*skb, len);
14762306a36Sopenharmony_ci	memcpy((*skb)->data + ST_NCI_I2C_MIN_SIZE, buf, len);
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	return 0;
15062306a36Sopenharmony_ci}
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci/*
15362306a36Sopenharmony_ci * Reads an ndlc frame from the chip.
15462306a36Sopenharmony_ci *
15562306a36Sopenharmony_ci * On ST_NCI, IRQ goes in idle state when read starts.
15662306a36Sopenharmony_ci */
15762306a36Sopenharmony_cistatic irqreturn_t st_nci_irq_thread_fn(int irq, void *phy_id)
15862306a36Sopenharmony_ci{
15962306a36Sopenharmony_ci	struct st_nci_i2c_phy *phy = phy_id;
16062306a36Sopenharmony_ci	struct sk_buff *skb = NULL;
16162306a36Sopenharmony_ci	int r;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	if (!phy || !phy->ndlc || irq != phy->i2c_dev->irq) {
16462306a36Sopenharmony_ci		WARN_ON_ONCE(1);
16562306a36Sopenharmony_ci		return IRQ_NONE;
16662306a36Sopenharmony_ci	}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	if (phy->ndlc->hard_fault)
16962306a36Sopenharmony_ci		return IRQ_HANDLED;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	if (!phy->ndlc->powered) {
17262306a36Sopenharmony_ci		st_nci_i2c_disable(phy);
17362306a36Sopenharmony_ci		return IRQ_HANDLED;
17462306a36Sopenharmony_ci	}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	r = st_nci_i2c_read(phy, &skb);
17762306a36Sopenharmony_ci	if (r == -EREMOTEIO || r == -ENOMEM || r == -EBADMSG)
17862306a36Sopenharmony_ci		return IRQ_HANDLED;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	ndlc_recv(phy->ndlc, skb);
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	return IRQ_HANDLED;
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cistatic const struct nfc_phy_ops i2c_phy_ops = {
18662306a36Sopenharmony_ci	.write = st_nci_i2c_write,
18762306a36Sopenharmony_ci	.enable = st_nci_i2c_enable,
18862306a36Sopenharmony_ci	.disable = st_nci_i2c_disable,
18962306a36Sopenharmony_ci};
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_cistatic const struct acpi_gpio_params reset_gpios = { 1, 0, false };
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_cistatic const struct acpi_gpio_mapping acpi_st_nci_gpios[] = {
19462306a36Sopenharmony_ci	{ "reset-gpios", &reset_gpios, 1 },
19562306a36Sopenharmony_ci	{},
19662306a36Sopenharmony_ci};
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_cistatic int st_nci_i2c_probe(struct i2c_client *client)
19962306a36Sopenharmony_ci{
20062306a36Sopenharmony_ci	struct device *dev = &client->dev;
20162306a36Sopenharmony_ci	struct st_nci_i2c_phy *phy;
20262306a36Sopenharmony_ci	int r;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
20562306a36Sopenharmony_ci		nfc_err(&client->dev, "Need I2C_FUNC_I2C\n");
20662306a36Sopenharmony_ci		return -ENODEV;
20762306a36Sopenharmony_ci	}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	phy = devm_kzalloc(dev, sizeof(struct st_nci_i2c_phy), GFP_KERNEL);
21062306a36Sopenharmony_ci	if (!phy)
21162306a36Sopenharmony_ci		return -ENOMEM;
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	phy->i2c_dev = client;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	i2c_set_clientdata(client, phy);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	r = devm_acpi_dev_add_driver_gpios(dev, acpi_st_nci_gpios);
21862306a36Sopenharmony_ci	if (r)
21962306a36Sopenharmony_ci		dev_dbg(dev, "Unable to add GPIO mapping table\n");
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	/* Get RESET GPIO */
22262306a36Sopenharmony_ci	phy->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
22362306a36Sopenharmony_ci	if (IS_ERR(phy->gpiod_reset)) {
22462306a36Sopenharmony_ci		nfc_err(dev, "Unable to get RESET GPIO\n");
22562306a36Sopenharmony_ci		return -ENODEV;
22662306a36Sopenharmony_ci	}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	phy->se_status.is_ese_present =
22962306a36Sopenharmony_ci				device_property_read_bool(dev, "ese-present");
23062306a36Sopenharmony_ci	phy->se_status.is_uicc_present =
23162306a36Sopenharmony_ci				device_property_read_bool(dev, "uicc-present");
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	r = ndlc_probe(phy, &i2c_phy_ops, &client->dev,
23462306a36Sopenharmony_ci			ST_NCI_FRAME_HEADROOM, ST_NCI_FRAME_TAILROOM,
23562306a36Sopenharmony_ci			&phy->ndlc, &phy->se_status);
23662306a36Sopenharmony_ci	if (r < 0) {
23762306a36Sopenharmony_ci		nfc_err(&client->dev, "Unable to register ndlc layer\n");
23862306a36Sopenharmony_ci		return r;
23962306a36Sopenharmony_ci	}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	phy->irq_active = true;
24262306a36Sopenharmony_ci	r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
24362306a36Sopenharmony_ci				st_nci_irq_thread_fn,
24462306a36Sopenharmony_ci				IRQF_ONESHOT,
24562306a36Sopenharmony_ci				ST_NCI_DRIVER_NAME, phy);
24662306a36Sopenharmony_ci	if (r < 0)
24762306a36Sopenharmony_ci		nfc_err(&client->dev, "Unable to register IRQ handler\n");
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	return r;
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_cistatic void st_nci_i2c_remove(struct i2c_client *client)
25362306a36Sopenharmony_ci{
25462306a36Sopenharmony_ci	struct st_nci_i2c_phy *phy = i2c_get_clientdata(client);
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	ndlc_remove(phy->ndlc);
25762306a36Sopenharmony_ci}
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_cistatic const struct i2c_device_id st_nci_i2c_id_table[] = {
26062306a36Sopenharmony_ci	{ST_NCI_DRIVER_NAME, 0},
26162306a36Sopenharmony_ci	{}
26262306a36Sopenharmony_ci};
26362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, st_nci_i2c_id_table);
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_cistatic const struct acpi_device_id st_nci_i2c_acpi_match[] __maybe_unused = {
26662306a36Sopenharmony_ci	{"SMO2101"},
26762306a36Sopenharmony_ci	{"SMO2102"},
26862306a36Sopenharmony_ci	{}
26962306a36Sopenharmony_ci};
27062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, st_nci_i2c_acpi_match);
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_cistatic const struct of_device_id of_st_nci_i2c_match[] __maybe_unused = {
27362306a36Sopenharmony_ci	{ .compatible = "st,st21nfcb-i2c", },
27462306a36Sopenharmony_ci	{ .compatible = "st,st21nfcb_i2c", },
27562306a36Sopenharmony_ci	{ .compatible = "st,st21nfcc-i2c", },
27662306a36Sopenharmony_ci	{}
27762306a36Sopenharmony_ci};
27862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, of_st_nci_i2c_match);
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_cistatic struct i2c_driver st_nci_i2c_driver = {
28162306a36Sopenharmony_ci	.driver = {
28262306a36Sopenharmony_ci		.name = ST_NCI_I2C_DRIVER_NAME,
28362306a36Sopenharmony_ci		.of_match_table = of_match_ptr(of_st_nci_i2c_match),
28462306a36Sopenharmony_ci		.acpi_match_table = ACPI_PTR(st_nci_i2c_acpi_match),
28562306a36Sopenharmony_ci	},
28662306a36Sopenharmony_ci	.probe = st_nci_i2c_probe,
28762306a36Sopenharmony_ci	.id_table = st_nci_i2c_id_table,
28862306a36Sopenharmony_ci	.remove = st_nci_i2c_remove,
28962306a36Sopenharmony_ci};
29062306a36Sopenharmony_cimodule_i2c_driver(st_nci_i2c_driver);
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ciMODULE_LICENSE("GPL");
29362306a36Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC);
294