162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * HCI based Driver for Inside Secure microread NFC Chip - i2c layer
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2013 Intel Corporation. All rights reserved.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/module.h>
1162306a36Sopenharmony_ci#include <linux/i2c.h>
1262306a36Sopenharmony_ci#include <linux/delay.h>
1362306a36Sopenharmony_ci#include <linux/slab.h>
1462306a36Sopenharmony_ci#include <linux/interrupt.h>
1562306a36Sopenharmony_ci#include <linux/gpio.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include <linux/nfc.h>
1862306a36Sopenharmony_ci#include <net/nfc/hci.h>
1962306a36Sopenharmony_ci#include <net/nfc/llc.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#include "microread.h"
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define MICROREAD_I2C_DRIVER_NAME "microread"
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define MICROREAD_I2C_FRAME_HEADROOM 1
2662306a36Sopenharmony_ci#define MICROREAD_I2C_FRAME_TAILROOM 1
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/* framing in HCI mode */
2962306a36Sopenharmony_ci#define MICROREAD_I2C_LLC_LEN		1
3062306a36Sopenharmony_ci#define MICROREAD_I2C_LLC_CRC		1
3162306a36Sopenharmony_ci#define MICROREAD_I2C_LLC_LEN_CRC	(MICROREAD_I2C_LLC_LEN + \
3262306a36Sopenharmony_ci					MICROREAD_I2C_LLC_CRC)
3362306a36Sopenharmony_ci#define MICROREAD_I2C_LLC_MIN_SIZE	(1 + MICROREAD_I2C_LLC_LEN_CRC)
3462306a36Sopenharmony_ci#define MICROREAD_I2C_LLC_MAX_PAYLOAD	29
3562306a36Sopenharmony_ci#define MICROREAD_I2C_LLC_MAX_SIZE	(MICROREAD_I2C_LLC_LEN_CRC + 1 + \
3662306a36Sopenharmony_ci					MICROREAD_I2C_LLC_MAX_PAYLOAD)
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistruct microread_i2c_phy {
3962306a36Sopenharmony_ci	struct i2c_client *i2c_dev;
4062306a36Sopenharmony_ci	struct nfc_hci_dev *hdev;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	int hard_fault;		/*
4362306a36Sopenharmony_ci				 * < 0 if hardware error occured (e.g. i2c err)
4462306a36Sopenharmony_ci				 * and prevents normal operation.
4562306a36Sopenharmony_ci				 */
4662306a36Sopenharmony_ci};
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci#define I2C_DUMP_SKB(info, skb)					\
4962306a36Sopenharmony_cido {								\
5062306a36Sopenharmony_ci	pr_debug("%s:\n", info);				\
5162306a36Sopenharmony_ci	print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET,	\
5262306a36Sopenharmony_ci		       16, 1, (skb)->data, (skb)->len, 0);	\
5362306a36Sopenharmony_ci} while (0)
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistatic void microread_i2c_add_len_crc(struct sk_buff *skb)
5662306a36Sopenharmony_ci{
5762306a36Sopenharmony_ci	int i;
5862306a36Sopenharmony_ci	u8 crc = 0;
5962306a36Sopenharmony_ci	int len;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	len = skb->len;
6262306a36Sopenharmony_ci	*(u8 *)skb_push(skb, 1) = len;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	for (i = 0; i < skb->len; i++)
6562306a36Sopenharmony_ci		crc = crc ^ skb->data[i];
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	skb_put_u8(skb, crc);
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistatic void microread_i2c_remove_len_crc(struct sk_buff *skb)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	skb_pull(skb, MICROREAD_I2C_FRAME_HEADROOM);
7362306a36Sopenharmony_ci	skb_trim(skb, MICROREAD_I2C_FRAME_TAILROOM);
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistatic int check_crc(const struct sk_buff *skb)
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	int i;
7962306a36Sopenharmony_ci	u8 crc = 0;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	for (i = 0; i < skb->len - 1; i++)
8262306a36Sopenharmony_ci		crc = crc ^ skb->data[i];
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	if (crc != skb->data[skb->len-1]) {
8562306a36Sopenharmony_ci		pr_err("CRC error 0x%x != 0x%x\n", crc, skb->data[skb->len-1]);
8662306a36Sopenharmony_ci		pr_info("%s: BAD CRC\n", __func__);
8762306a36Sopenharmony_ci		return -EPERM;
8862306a36Sopenharmony_ci	}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	return 0;
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic int microread_i2c_enable(void *phy_id)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	return 0;
9662306a36Sopenharmony_ci}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic void microread_i2c_disable(void *phy_id)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	return;
10162306a36Sopenharmony_ci}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistatic int microread_i2c_write(void *phy_id, struct sk_buff *skb)
10462306a36Sopenharmony_ci{
10562306a36Sopenharmony_ci	int r;
10662306a36Sopenharmony_ci	struct microread_i2c_phy *phy = phy_id;
10762306a36Sopenharmony_ci	struct i2c_client *client = phy->i2c_dev;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	if (phy->hard_fault != 0)
11062306a36Sopenharmony_ci		return phy->hard_fault;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	usleep_range(3000, 6000);
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	microread_i2c_add_len_crc(skb);
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	I2C_DUMP_SKB("i2c frame written", skb);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	r = i2c_master_send(client, skb->data, skb->len);
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	if (r == -EREMOTEIO) {	/* Retry, chip was in standby */
12162306a36Sopenharmony_ci		usleep_range(6000, 10000);
12262306a36Sopenharmony_ci		r = i2c_master_send(client, skb->data, skb->len);
12362306a36Sopenharmony_ci	}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	if (r >= 0) {
12662306a36Sopenharmony_ci		if (r != skb->len)
12762306a36Sopenharmony_ci			r = -EREMOTEIO;
12862306a36Sopenharmony_ci		else
12962306a36Sopenharmony_ci			r = 0;
13062306a36Sopenharmony_ci	}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	microread_i2c_remove_len_crc(skb);
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	return r;
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cistatic int microread_i2c_read(struct microread_i2c_phy *phy,
13962306a36Sopenharmony_ci			      struct sk_buff **skb)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	int r;
14262306a36Sopenharmony_ci	u8 len;
14362306a36Sopenharmony_ci	u8 tmp[MICROREAD_I2C_LLC_MAX_SIZE - 1];
14462306a36Sopenharmony_ci	struct i2c_client *client = phy->i2c_dev;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	r = i2c_master_recv(client, &len, 1);
14762306a36Sopenharmony_ci	if (r != 1) {
14862306a36Sopenharmony_ci		nfc_err(&client->dev, "cannot read len byte\n");
14962306a36Sopenharmony_ci		return -EREMOTEIO;
15062306a36Sopenharmony_ci	}
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	if ((len < MICROREAD_I2C_LLC_MIN_SIZE) ||
15362306a36Sopenharmony_ci	    (len > MICROREAD_I2C_LLC_MAX_SIZE)) {
15462306a36Sopenharmony_ci		nfc_err(&client->dev, "invalid len byte\n");
15562306a36Sopenharmony_ci		r = -EBADMSG;
15662306a36Sopenharmony_ci		goto flush;
15762306a36Sopenharmony_ci	}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	*skb = alloc_skb(1 + len, GFP_KERNEL);
16062306a36Sopenharmony_ci	if (*skb == NULL) {
16162306a36Sopenharmony_ci		r = -ENOMEM;
16262306a36Sopenharmony_ci		goto flush;
16362306a36Sopenharmony_ci	}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	skb_put_u8(*skb, len);
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	r = i2c_master_recv(client, skb_put(*skb, len), len);
16862306a36Sopenharmony_ci	if (r != len) {
16962306a36Sopenharmony_ci		kfree_skb(*skb);
17062306a36Sopenharmony_ci		return -EREMOTEIO;
17162306a36Sopenharmony_ci	}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	I2C_DUMP_SKB("cc frame read", *skb);
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	r = check_crc(*skb);
17662306a36Sopenharmony_ci	if (r != 0) {
17762306a36Sopenharmony_ci		kfree_skb(*skb);
17862306a36Sopenharmony_ci		r = -EBADMSG;
17962306a36Sopenharmony_ci		goto flush;
18062306a36Sopenharmony_ci	}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	skb_pull(*skb, 1);
18362306a36Sopenharmony_ci	skb_trim(*skb, (*skb)->len - MICROREAD_I2C_FRAME_TAILROOM);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	usleep_range(3000, 6000);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	return 0;
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ciflush:
19062306a36Sopenharmony_ci	if (i2c_master_recv(client, tmp, sizeof(tmp)) < 0)
19162306a36Sopenharmony_ci		r = -EREMOTEIO;
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	usleep_range(3000, 6000);
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	return r;
19662306a36Sopenharmony_ci}
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_cistatic irqreturn_t microread_i2c_irq_thread_fn(int irq, void *phy_id)
19962306a36Sopenharmony_ci{
20062306a36Sopenharmony_ci	struct microread_i2c_phy *phy = phy_id;
20162306a36Sopenharmony_ci	struct sk_buff *skb = NULL;
20262306a36Sopenharmony_ci	int r;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	if (!phy || irq != phy->i2c_dev->irq) {
20562306a36Sopenharmony_ci		WARN_ON_ONCE(1);
20662306a36Sopenharmony_ci		return IRQ_NONE;
20762306a36Sopenharmony_ci	}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	if (phy->hard_fault != 0)
21062306a36Sopenharmony_ci		return IRQ_HANDLED;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	r = microread_i2c_read(phy, &skb);
21362306a36Sopenharmony_ci	if (r == -EREMOTEIO) {
21462306a36Sopenharmony_ci		phy->hard_fault = r;
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci		nfc_hci_recv_frame(phy->hdev, NULL);
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci		return IRQ_HANDLED;
21962306a36Sopenharmony_ci	} else if ((r == -ENOMEM) || (r == -EBADMSG)) {
22062306a36Sopenharmony_ci		return IRQ_HANDLED;
22162306a36Sopenharmony_ci	}
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	nfc_hci_recv_frame(phy->hdev, skb);
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	return IRQ_HANDLED;
22662306a36Sopenharmony_ci}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_cistatic const struct nfc_phy_ops i2c_phy_ops = {
22962306a36Sopenharmony_ci	.write = microread_i2c_write,
23062306a36Sopenharmony_ci	.enable = microread_i2c_enable,
23162306a36Sopenharmony_ci	.disable = microread_i2c_disable,
23262306a36Sopenharmony_ci};
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_cistatic int microread_i2c_probe(struct i2c_client *client)
23562306a36Sopenharmony_ci{
23662306a36Sopenharmony_ci	struct microread_i2c_phy *phy;
23762306a36Sopenharmony_ci	int r;
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	phy = devm_kzalloc(&client->dev, sizeof(struct microread_i2c_phy),
24062306a36Sopenharmony_ci			   GFP_KERNEL);
24162306a36Sopenharmony_ci	if (!phy)
24262306a36Sopenharmony_ci		return -ENOMEM;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	i2c_set_clientdata(client, phy);
24562306a36Sopenharmony_ci	phy->i2c_dev = client;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	r = request_threaded_irq(client->irq, NULL, microread_i2c_irq_thread_fn,
24862306a36Sopenharmony_ci				 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
24962306a36Sopenharmony_ci				 MICROREAD_I2C_DRIVER_NAME, phy);
25062306a36Sopenharmony_ci	if (r) {
25162306a36Sopenharmony_ci		nfc_err(&client->dev, "Unable to register IRQ handler\n");
25262306a36Sopenharmony_ci		return r;
25362306a36Sopenharmony_ci	}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	r = microread_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME,
25662306a36Sopenharmony_ci			    MICROREAD_I2C_FRAME_HEADROOM,
25762306a36Sopenharmony_ci			    MICROREAD_I2C_FRAME_TAILROOM,
25862306a36Sopenharmony_ci			    MICROREAD_I2C_LLC_MAX_PAYLOAD, &phy->hdev);
25962306a36Sopenharmony_ci	if (r < 0)
26062306a36Sopenharmony_ci		goto err_irq;
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	return 0;
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_cierr_irq:
26562306a36Sopenharmony_ci	free_irq(client->irq, phy);
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	return r;
26862306a36Sopenharmony_ci}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_cistatic void microread_i2c_remove(struct i2c_client *client)
27162306a36Sopenharmony_ci{
27262306a36Sopenharmony_ci	struct microread_i2c_phy *phy = i2c_get_clientdata(client);
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	microread_remove(phy->hdev);
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	free_irq(client->irq, phy);
27762306a36Sopenharmony_ci}
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_cistatic const struct i2c_device_id microread_i2c_id[] = {
28062306a36Sopenharmony_ci	{ MICROREAD_I2C_DRIVER_NAME, 0},
28162306a36Sopenharmony_ci	{ }
28262306a36Sopenharmony_ci};
28362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, microread_i2c_id);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_cistatic struct i2c_driver microread_i2c_driver = {
28662306a36Sopenharmony_ci	.driver = {
28762306a36Sopenharmony_ci		.name = MICROREAD_I2C_DRIVER_NAME,
28862306a36Sopenharmony_ci	},
28962306a36Sopenharmony_ci	.probe		= microread_i2c_probe,
29062306a36Sopenharmony_ci	.remove		= microread_i2c_remove,
29162306a36Sopenharmony_ci	.id_table	= microread_i2c_id,
29262306a36Sopenharmony_ci};
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_cimodule_i2c_driver(microread_i2c_driver);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ciMODULE_LICENSE("GPL");
29762306a36Sopenharmony_ciMODULE_DESCRIPTION(DRIVER_DESC);
298