cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

i2c.c (6172B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * HCI based Driver for Inside Secure microread NFC Chip - i2c layer
      4 *
      5 * Copyright (C) 2013 Intel Corporation. All rights reserved.
      6 */
      7
      8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      9
     10#include <linux/module.h>
     11#include <linux/i2c.h>
     12#include <linux/delay.h>
     13#include <linux/slab.h>
     14#include <linux/interrupt.h>
     15#include <linux/gpio.h>
     16
     17#include <linux/nfc.h>
     18#include <net/nfc/hci.h>
     19#include <net/nfc/llc.h>
     20
     21#include "microread.h"
     22
     23#define MICROREAD_I2C_DRIVER_NAME "microread"
     24
     25#define MICROREAD_I2C_FRAME_HEADROOM 1
     26#define MICROREAD_I2C_FRAME_TAILROOM 1
     27
     28/* framing in HCI mode */
     29#define MICROREAD_I2C_LLC_LEN		1
     30#define MICROREAD_I2C_LLC_CRC		1
     31#define MICROREAD_I2C_LLC_LEN_CRC	(MICROREAD_I2C_LLC_LEN + \
     32					MICROREAD_I2C_LLC_CRC)
     33#define MICROREAD_I2C_LLC_MIN_SIZE	(1 + MICROREAD_I2C_LLC_LEN_CRC)
     34#define MICROREAD_I2C_LLC_MAX_PAYLOAD	29
     35#define MICROREAD_I2C_LLC_MAX_SIZE	(MICROREAD_I2C_LLC_LEN_CRC + 1 + \
     36					MICROREAD_I2C_LLC_MAX_PAYLOAD)
     37
     38struct microread_i2c_phy {
     39	struct i2c_client *i2c_dev;
     40	struct nfc_hci_dev *hdev;
     41
     42	int hard_fault;		/*
     43				 * < 0 if hardware error occured (e.g. i2c err)
     44				 * and prevents normal operation.
     45				 */
     46};
     47
     48#define I2C_DUMP_SKB(info, skb)					\
     49do {								\
     50	pr_debug("%s:\n", info);				\
     51	print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET,	\
     52		       16, 1, (skb)->data, (skb)->len, 0);	\
     53} while (0)
     54
     55static void microread_i2c_add_len_crc(struct sk_buff *skb)
     56{
     57	int i;
     58	u8 crc = 0;
     59	int len;
     60
     61	len = skb->len;
     62	*(u8 *)skb_push(skb, 1) = len;
     63
     64	for (i = 0; i < skb->len; i++)
     65		crc = crc ^ skb->data[i];
     66
     67	skb_put_u8(skb, crc);
     68}
     69
     70static void microread_i2c_remove_len_crc(struct sk_buff *skb)
     71{
     72	skb_pull(skb, MICROREAD_I2C_FRAME_HEADROOM);
     73	skb_trim(skb, MICROREAD_I2C_FRAME_TAILROOM);
     74}
     75
     76static int check_crc(const struct sk_buff *skb)
     77{
     78	int i;
     79	u8 crc = 0;
     80
     81	for (i = 0; i < skb->len - 1; i++)
     82		crc = crc ^ skb->data[i];
     83
     84	if (crc != skb->data[skb->len-1]) {
     85		pr_err("CRC error 0x%x != 0x%x\n", crc, skb->data[skb->len-1]);
     86		pr_info("%s: BAD CRC\n", __func__);
     87		return -EPERM;
     88	}
     89
     90	return 0;
     91}
     92
     93static int microread_i2c_enable(void *phy_id)
     94{
     95	return 0;
     96}
     97
     98static void microread_i2c_disable(void *phy_id)
     99{
    100	return;
    101}
    102
    103static int microread_i2c_write(void *phy_id, struct sk_buff *skb)
    104{
    105	int r;
    106	struct microread_i2c_phy *phy = phy_id;
    107	struct i2c_client *client = phy->i2c_dev;
    108
    109	if (phy->hard_fault != 0)
    110		return phy->hard_fault;
    111
    112	usleep_range(3000, 6000);
    113
    114	microread_i2c_add_len_crc(skb);
    115
    116	I2C_DUMP_SKB("i2c frame written", skb);
    117
    118	r = i2c_master_send(client, skb->data, skb->len);
    119
    120	if (r == -EREMOTEIO) {	/* Retry, chip was in standby */
    121		usleep_range(6000, 10000);
    122		r = i2c_master_send(client, skb->data, skb->len);
    123	}
    124
    125	if (r >= 0) {
    126		if (r != skb->len)
    127			r = -EREMOTEIO;
    128		else
    129			r = 0;
    130	}
    131
    132	microread_i2c_remove_len_crc(skb);
    133
    134	return r;
    135}
    136
    137
    138static int microread_i2c_read(struct microread_i2c_phy *phy,
    139			      struct sk_buff **skb)
    140{
    141	int r;
    142	u8 len;
    143	u8 tmp[MICROREAD_I2C_LLC_MAX_SIZE - 1];
    144	struct i2c_client *client = phy->i2c_dev;
    145
    146	r = i2c_master_recv(client, &len, 1);
    147	if (r != 1) {
    148		nfc_err(&client->dev, "cannot read len byte\n");
    149		return -EREMOTEIO;
    150	}
    151
    152	if ((len < MICROREAD_I2C_LLC_MIN_SIZE) ||
    153	    (len > MICROREAD_I2C_LLC_MAX_SIZE)) {
    154		nfc_err(&client->dev, "invalid len byte\n");
    155		r = -EBADMSG;
    156		goto flush;
    157	}
    158
    159	*skb = alloc_skb(1 + len, GFP_KERNEL);
    160	if (*skb == NULL) {
    161		r = -ENOMEM;
    162		goto flush;
    163	}
    164
    165	skb_put_u8(*skb, len);
    166
    167	r = i2c_master_recv(client, skb_put(*skb, len), len);
    168	if (r != len) {
    169		kfree_skb(*skb);
    170		return -EREMOTEIO;
    171	}
    172
    173	I2C_DUMP_SKB("cc frame read", *skb);
    174
    175	r = check_crc(*skb);
    176	if (r != 0) {
    177		kfree_skb(*skb);
    178		r = -EBADMSG;
    179		goto flush;
    180	}
    181
    182	skb_pull(*skb, 1);
    183	skb_trim(*skb, (*skb)->len - MICROREAD_I2C_FRAME_TAILROOM);
    184
    185	usleep_range(3000, 6000);
    186
    187	return 0;
    188
    189flush:
    190	if (i2c_master_recv(client, tmp, sizeof(tmp)) < 0)
    191		r = -EREMOTEIO;
    192
    193	usleep_range(3000, 6000);
    194
    195	return r;
    196}
    197
    198static irqreturn_t microread_i2c_irq_thread_fn(int irq, void *phy_id)
    199{
    200	struct microread_i2c_phy *phy = phy_id;
    201	struct sk_buff *skb = NULL;
    202	int r;
    203
    204	if (!phy || irq != phy->i2c_dev->irq) {
    205		WARN_ON_ONCE(1);
    206		return IRQ_NONE;
    207	}
    208
    209	if (phy->hard_fault != 0)
    210		return IRQ_HANDLED;
    211
    212	r = microread_i2c_read(phy, &skb);
    213	if (r == -EREMOTEIO) {
    214		phy->hard_fault = r;
    215
    216		nfc_hci_recv_frame(phy->hdev, NULL);
    217
    218		return IRQ_HANDLED;
    219	} else if ((r == -ENOMEM) || (r == -EBADMSG)) {
    220		return IRQ_HANDLED;
    221	}
    222
    223	nfc_hci_recv_frame(phy->hdev, skb);
    224
    225	return IRQ_HANDLED;
    226}
    227
    228static const struct nfc_phy_ops i2c_phy_ops = {
    229	.write = microread_i2c_write,
    230	.enable = microread_i2c_enable,
    231	.disable = microread_i2c_disable,
    232};
    233
    234static int microread_i2c_probe(struct i2c_client *client,
    235			       const struct i2c_device_id *id)
    236{
    237	struct microread_i2c_phy *phy;
    238	int r;
    239
    240	phy = devm_kzalloc(&client->dev, sizeof(struct microread_i2c_phy),
    241			   GFP_KERNEL);
    242	if (!phy)
    243		return -ENOMEM;
    244
    245	i2c_set_clientdata(client, phy);
    246	phy->i2c_dev = client;
    247
    248	r = request_threaded_irq(client->irq, NULL, microread_i2c_irq_thread_fn,
    249				 IRQF_TRIGGER_RISING | IRQF_ONESHOT,
    250				 MICROREAD_I2C_DRIVER_NAME, phy);
    251	if (r) {
    252		nfc_err(&client->dev, "Unable to register IRQ handler\n");
    253		return r;
    254	}
    255
    256	r = microread_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME,
    257			    MICROREAD_I2C_FRAME_HEADROOM,
    258			    MICROREAD_I2C_FRAME_TAILROOM,
    259			    MICROREAD_I2C_LLC_MAX_PAYLOAD, &phy->hdev);
    260	if (r < 0)
    261		goto err_irq;
    262
    263	return 0;
    264
    265err_irq:
    266	free_irq(client->irq, phy);
    267
    268	return r;
    269}
    270
    271static int microread_i2c_remove(struct i2c_client *client)
    272{
    273	struct microread_i2c_phy *phy = i2c_get_clientdata(client);
    274
    275	microread_remove(phy->hdev);
    276
    277	free_irq(client->irq, phy);
    278
    279	return 0;
    280}
    281
    282static const struct i2c_device_id microread_i2c_id[] = {
    283	{ MICROREAD_I2C_DRIVER_NAME, 0},
    284	{ }
    285};
    286MODULE_DEVICE_TABLE(i2c, microread_i2c_id);
    287
    288static struct i2c_driver microread_i2c_driver = {
    289	.driver = {
    290		.name = MICROREAD_I2C_DRIVER_NAME,
    291	},
    292	.probe		= microread_i2c_probe,
    293	.remove		= microread_i2c_remove,
    294	.id_table	= microread_i2c_id,
    295};
    296
    297module_i2c_driver(microread_i2c_driver);
    298
    299MODULE_LICENSE("GPL");
    300MODULE_DESCRIPTION(DRIVER_DESC);