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

tpm_i2c_atmel.c (6019B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * ATMEL I2C TPM AT97SC3204T
      4 *
      5 * Copyright (C) 2012 V Lab Technologies
      6 *  Teddy Reed <teddy@prosauce.org>
      7 * Copyright (C) 2013, Obsidian Research Corp.
      8 *  Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
      9 * Device driver for ATMEL I2C TPMs.
     10 *
     11 * Teddy Reed determined the basic I2C command flow, unlike other I2C TPM
     12 * devices the raw TCG formatted TPM command data is written via I2C and then
     13 * raw TCG formatted TPM command data is returned via I2C.
     14 *
     15 * TGC status/locality/etc functions seen in the LPC implementation do not
     16 * seem to be present.
     17 */
     18#include <linux/init.h>
     19#include <linux/module.h>
     20#include <linux/moduleparam.h>
     21#include <linux/slab.h>
     22#include <linux/i2c.h>
     23#include "tpm.h"
     24
     25#define I2C_DRIVER_NAME "tpm_i2c_atmel"
     26
     27#define TPM_I2C_SHORT_TIMEOUT  750     /* ms */
     28#define TPM_I2C_LONG_TIMEOUT   2000    /* 2 sec */
     29
     30#define ATMEL_STS_OK 1
     31
     32struct priv_data {
     33	size_t len;
     34	/* This is the amount we read on the first try. 25 was chosen to fit a
     35	 * fair number of read responses in the buffer so a 2nd retry can be
     36	 * avoided in small message cases. */
     37	u8 buffer[sizeof(struct tpm_header) + 25];
     38};
     39
     40static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len)
     41{
     42	struct priv_data *priv = dev_get_drvdata(&chip->dev);
     43	struct i2c_client *client = to_i2c_client(chip->dev.parent);
     44	s32 status;
     45
     46	priv->len = 0;
     47
     48	if (len <= 2)
     49		return -EIO;
     50
     51	status = i2c_master_send(client, buf, len);
     52
     53	dev_dbg(&chip->dev,
     54		"%s(buf=%*ph len=%0zx) -> sts=%d\n", __func__,
     55		(int)min_t(size_t, 64, len), buf, len, status);
     56
     57	if (status < 0)
     58		return status;
     59
     60	/* The upper layer does not support incomplete sends. */
     61	if (status != len)
     62		return -E2BIG;
     63
     64	return 0;
     65}
     66
     67static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
     68{
     69	struct priv_data *priv = dev_get_drvdata(&chip->dev);
     70	struct i2c_client *client = to_i2c_client(chip->dev.parent);
     71	struct tpm_header *hdr = (struct tpm_header *)priv->buffer;
     72	u32 expected_len;
     73	int rc;
     74
     75	if (priv->len == 0)
     76		return -EIO;
     77
     78	/* Get the message size from the message header, if we didn't get the
     79	 * whole message in read_status then we need to re-read the
     80	 * message. */
     81	expected_len = be32_to_cpu(hdr->length);
     82	if (expected_len > count)
     83		return -ENOMEM;
     84
     85	if (priv->len >= expected_len) {
     86		dev_dbg(&chip->dev,
     87			"%s early(buf=%*ph count=%0zx) -> ret=%d\n", __func__,
     88			(int)min_t(size_t, 64, expected_len), buf, count,
     89			expected_len);
     90		memcpy(buf, priv->buffer, expected_len);
     91		return expected_len;
     92	}
     93
     94	rc = i2c_master_recv(client, buf, expected_len);
     95	dev_dbg(&chip->dev,
     96		"%s reread(buf=%*ph count=%0zx) -> ret=%d\n", __func__,
     97		(int)min_t(size_t, 64, expected_len), buf, count,
     98		expected_len);
     99	return rc;
    100}
    101
    102static void i2c_atmel_cancel(struct tpm_chip *chip)
    103{
    104	dev_err(&chip->dev, "TPM operation cancellation was requested, but is not supported");
    105}
    106
    107static u8 i2c_atmel_read_status(struct tpm_chip *chip)
    108{
    109	struct priv_data *priv = dev_get_drvdata(&chip->dev);
    110	struct i2c_client *client = to_i2c_client(chip->dev.parent);
    111	int rc;
    112
    113	/* The TPM fails the I2C read until it is ready, so we do the entire
    114	 * transfer here and buffer it locally. This way the common code can
    115	 * properly handle the timeouts. */
    116	priv->len = 0;
    117	memset(priv->buffer, 0, sizeof(priv->buffer));
    118
    119
    120	/* Once the TPM has completed the command the command remains readable
    121	 * until another command is issued. */
    122	rc = i2c_master_recv(client, priv->buffer, sizeof(priv->buffer));
    123	dev_dbg(&chip->dev,
    124		"%s: sts=%d", __func__, rc);
    125	if (rc <= 0)
    126		return 0;
    127
    128	priv->len = rc;
    129
    130	return ATMEL_STS_OK;
    131}
    132
    133static bool i2c_atmel_req_canceled(struct tpm_chip *chip, u8 status)
    134{
    135	return false;
    136}
    137
    138static const struct tpm_class_ops i2c_atmel = {
    139	.flags = TPM_OPS_AUTO_STARTUP,
    140	.status = i2c_atmel_read_status,
    141	.recv = i2c_atmel_recv,
    142	.send = i2c_atmel_send,
    143	.cancel = i2c_atmel_cancel,
    144	.req_complete_mask = ATMEL_STS_OK,
    145	.req_complete_val = ATMEL_STS_OK,
    146	.req_canceled = i2c_atmel_req_canceled,
    147};
    148
    149static int i2c_atmel_probe(struct i2c_client *client,
    150			   const struct i2c_device_id *id)
    151{
    152	struct tpm_chip *chip;
    153	struct device *dev = &client->dev;
    154	struct priv_data *priv;
    155
    156	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
    157		return -ENODEV;
    158
    159	chip = tpmm_chip_alloc(dev, &i2c_atmel);
    160	if (IS_ERR(chip))
    161		return PTR_ERR(chip);
    162
    163	priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL);
    164	if (!priv)
    165		return -ENOMEM;
    166
    167	/* Default timeouts */
    168	chip->timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
    169	chip->timeout_b = msecs_to_jiffies(TPM_I2C_LONG_TIMEOUT);
    170	chip->timeout_c = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
    171	chip->timeout_d = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
    172
    173	dev_set_drvdata(&chip->dev, priv);
    174
    175	/* There is no known way to probe for this device, and all version
    176	 * information seems to be read via TPM commands. Thus we rely on the
    177	 * TPM startup process in the common code to detect the device. */
    178
    179	return tpm_chip_register(chip);
    180}
    181
    182static int i2c_atmel_remove(struct i2c_client *client)
    183{
    184	struct device *dev = &(client->dev);
    185	struct tpm_chip *chip = dev_get_drvdata(dev);
    186	tpm_chip_unregister(chip);
    187	return 0;
    188}
    189
    190static const struct i2c_device_id i2c_atmel_id[] = {
    191	{I2C_DRIVER_NAME, 0},
    192	{}
    193};
    194MODULE_DEVICE_TABLE(i2c, i2c_atmel_id);
    195
    196#ifdef CONFIG_OF
    197static const struct of_device_id i2c_atmel_of_match[] = {
    198	{.compatible = "atmel,at97sc3204t"},
    199	{},
    200};
    201MODULE_DEVICE_TABLE(of, i2c_atmel_of_match);
    202#endif
    203
    204static SIMPLE_DEV_PM_OPS(i2c_atmel_pm_ops, tpm_pm_suspend, tpm_pm_resume);
    205
    206static struct i2c_driver i2c_atmel_driver = {
    207	.id_table = i2c_atmel_id,
    208	.probe = i2c_atmel_probe,
    209	.remove = i2c_atmel_remove,
    210	.driver = {
    211		.name = I2C_DRIVER_NAME,
    212		.pm = &i2c_atmel_pm_ops,
    213		.of_match_table = of_match_ptr(i2c_atmel_of_match),
    214	},
    215};
    216
    217module_i2c_driver(i2c_atmel_driver);
    218
    219MODULE_AUTHOR("Jason Gunthorpe <jgunthorpe@obsidianresearch.com>");
    220MODULE_DESCRIPTION("Atmel TPM I2C Driver");
    221MODULE_LICENSE("GPL");