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

spi.c (11621B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * STMicroelectronics TPM SPI Linux driver for TPM ST33ZP24
      4 * Copyright (C) 2009 - 2016 STMicroelectronics
      5 */
      6
      7#include <linux/module.h>
      8#include <linux/spi/spi.h>
      9#include <linux/gpio.h>
     10#include <linux/gpio/consumer.h>
     11#include <linux/of_irq.h>
     12#include <linux/of_gpio.h>
     13#include <linux/acpi.h>
     14#include <linux/tpm.h>
     15#include <linux/platform_data/st33zp24.h>
     16
     17#include "../tpm.h"
     18#include "st33zp24.h"
     19
     20#define TPM_DATA_FIFO           0x24
     21#define TPM_INTF_CAPABILITY     0x14
     22
     23#define TPM_DUMMY_BYTE		0x00
     24
     25#define MAX_SPI_LATENCY		15
     26#define LOCALITY0		0
     27
     28#define ST33ZP24_OK					0x5A
     29#define ST33ZP24_UNDEFINED_ERR				0x80
     30#define ST33ZP24_BADLOCALITY				0x81
     31#define ST33ZP24_TISREGISTER_UNKNOWN			0x82
     32#define ST33ZP24_LOCALITY_NOT_ACTIVATED			0x83
     33#define ST33ZP24_HASH_END_BEFORE_HASH_START		0x84
     34#define ST33ZP24_BAD_COMMAND_ORDER			0x85
     35#define ST33ZP24_INCORECT_RECEIVED_LENGTH		0x86
     36#define ST33ZP24_TPM_FIFO_OVERFLOW			0x89
     37#define ST33ZP24_UNEXPECTED_READ_FIFO			0x8A
     38#define ST33ZP24_UNEXPECTED_WRITE_FIFO			0x8B
     39#define ST33ZP24_CMDRDY_SET_WHEN_PROCESSING_HASH_END	0x90
     40#define ST33ZP24_DUMMY_BYTES				0x00
     41
     42/*
     43 * TPM command can be up to 2048 byte, A TPM response can be up to
     44 * 1024 byte.
     45 * Between command and response, there are latency byte (up to 15
     46 * usually on st33zp24 2 are enough).
     47 *
     48 * Overall when sending a command and expecting an answer we need if
     49 * worst case:
     50 * 2048 (for the TPM command) + 1024 (for the TPM answer).  We need
     51 * some latency byte before the answer is available (max 15).
     52 * We have 2048 + 1024 + 15.
     53 */
     54#define ST33ZP24_SPI_BUFFER_SIZE (ST33ZP24_BUFSIZE + (ST33ZP24_BUFSIZE / 2) +\
     55				  MAX_SPI_LATENCY)
     56
     57
     58struct st33zp24_spi_phy {
     59	struct spi_device *spi_device;
     60
     61	u8 tx_buf[ST33ZP24_SPI_BUFFER_SIZE];
     62	u8 rx_buf[ST33ZP24_SPI_BUFFER_SIZE];
     63
     64	int io_lpcpd;
     65	int latency;
     66};
     67
     68static int st33zp24_status_to_errno(u8 code)
     69{
     70	switch (code) {
     71	case ST33ZP24_OK:
     72		return 0;
     73	case ST33ZP24_UNDEFINED_ERR:
     74	case ST33ZP24_BADLOCALITY:
     75	case ST33ZP24_TISREGISTER_UNKNOWN:
     76	case ST33ZP24_LOCALITY_NOT_ACTIVATED:
     77	case ST33ZP24_HASH_END_BEFORE_HASH_START:
     78	case ST33ZP24_BAD_COMMAND_ORDER:
     79	case ST33ZP24_UNEXPECTED_READ_FIFO:
     80	case ST33ZP24_UNEXPECTED_WRITE_FIFO:
     81	case ST33ZP24_CMDRDY_SET_WHEN_PROCESSING_HASH_END:
     82		return -EPROTO;
     83	case ST33ZP24_INCORECT_RECEIVED_LENGTH:
     84	case ST33ZP24_TPM_FIFO_OVERFLOW:
     85		return -EMSGSIZE;
     86	case ST33ZP24_DUMMY_BYTES:
     87		return -ENOSYS;
     88	}
     89	return code;
     90}
     91
     92/*
     93 * st33zp24_spi_send
     94 * Send byte to the TIS register according to the ST33ZP24 SPI protocol.
     95 * @param: phy_id, the phy description
     96 * @param: tpm_register, the tpm tis register where the data should be written
     97 * @param: tpm_data, the tpm_data to write inside the tpm_register
     98 * @param: tpm_size, The length of the data
     99 * @return: should be zero if success else a negative error code.
    100 */
    101static int st33zp24_spi_send(void *phy_id, u8 tpm_register, u8 *tpm_data,
    102			     int tpm_size)
    103{
    104	int total_length = 0, ret = 0;
    105	struct st33zp24_spi_phy *phy = phy_id;
    106	struct spi_device *dev = phy->spi_device;
    107	struct spi_transfer spi_xfer = {
    108		.tx_buf = phy->tx_buf,
    109		.rx_buf = phy->rx_buf,
    110	};
    111
    112	/* Pre-Header */
    113	phy->tx_buf[total_length++] = TPM_WRITE_DIRECTION | LOCALITY0;
    114	phy->tx_buf[total_length++] = tpm_register;
    115
    116	if (tpm_size > 0 && tpm_register == TPM_DATA_FIFO) {
    117		phy->tx_buf[total_length++] = tpm_size >> 8;
    118		phy->tx_buf[total_length++] = tpm_size;
    119	}
    120
    121	memcpy(&phy->tx_buf[total_length], tpm_data, tpm_size);
    122	total_length += tpm_size;
    123
    124	memset(&phy->tx_buf[total_length], TPM_DUMMY_BYTE, phy->latency);
    125
    126	spi_xfer.len = total_length + phy->latency;
    127
    128	ret = spi_sync_transfer(dev, &spi_xfer, 1);
    129	if (ret == 0)
    130		ret = phy->rx_buf[total_length + phy->latency - 1];
    131
    132	return st33zp24_status_to_errno(ret);
    133} /* st33zp24_spi_send() */
    134
    135/*
    136 * st33zp24_spi_read8_recv
    137 * Recv byte from the TIS register according to the ST33ZP24 SPI protocol.
    138 * @param: phy_id, the phy description
    139 * @param: tpm_register, the tpm tis register where the data should be read
    140 * @param: tpm_data, the TPM response
    141 * @param: tpm_size, tpm TPM response size to read.
    142 * @return: should be zero if success else a negative error code.
    143 */
    144static int st33zp24_spi_read8_reg(void *phy_id, u8 tpm_register, u8 *tpm_data,
    145				  int tpm_size)
    146{
    147	int total_length = 0, ret;
    148	struct st33zp24_spi_phy *phy = phy_id;
    149	struct spi_device *dev = phy->spi_device;
    150	struct spi_transfer spi_xfer = {
    151		.tx_buf = phy->tx_buf,
    152		.rx_buf = phy->rx_buf,
    153	};
    154
    155	/* Pre-Header */
    156	phy->tx_buf[total_length++] = LOCALITY0;
    157	phy->tx_buf[total_length++] = tpm_register;
    158
    159	memset(&phy->tx_buf[total_length], TPM_DUMMY_BYTE,
    160	       phy->latency + tpm_size);
    161
    162	spi_xfer.len = total_length + phy->latency + tpm_size;
    163
    164	/* header + status byte + size of the data + status byte */
    165	ret = spi_sync_transfer(dev, &spi_xfer, 1);
    166	if (tpm_size > 0 && ret == 0) {
    167		ret = phy->rx_buf[total_length + phy->latency - 1];
    168
    169		memcpy(tpm_data, phy->rx_buf + total_length + phy->latency,
    170		       tpm_size);
    171	}
    172
    173	return ret;
    174} /* st33zp24_spi_read8_reg() */
    175
    176/*
    177 * st33zp24_spi_recv
    178 * Recv byte from the TIS register according to the ST33ZP24 SPI protocol.
    179 * @param: phy_id, the phy description
    180 * @param: tpm_register, the tpm tis register where the data should be read
    181 * @param: tpm_data, the TPM response
    182 * @param: tpm_size, tpm TPM response size to read.
    183 * @return: number of byte read successfully: should be one if success.
    184 */
    185static int st33zp24_spi_recv(void *phy_id, u8 tpm_register, u8 *tpm_data,
    186			     int tpm_size)
    187{
    188	int ret;
    189
    190	ret = st33zp24_spi_read8_reg(phy_id, tpm_register, tpm_data, tpm_size);
    191	if (!st33zp24_status_to_errno(ret))
    192		return tpm_size;
    193	return ret;
    194} /* st33zp24_spi_recv() */
    195
    196static int st33zp24_spi_evaluate_latency(void *phy_id)
    197{
    198	struct st33zp24_spi_phy *phy = phy_id;
    199	int latency = 1, status = 0;
    200	u8 data = 0;
    201
    202	while (!status && latency < MAX_SPI_LATENCY) {
    203		phy->latency = latency;
    204		status = st33zp24_spi_read8_reg(phy_id, TPM_INTF_CAPABILITY,
    205						&data, 1);
    206		latency++;
    207	}
    208	if (status < 0)
    209		return status;
    210	if (latency == MAX_SPI_LATENCY)
    211		return -ENODEV;
    212
    213	return latency - 1;
    214} /* evaluate_latency() */
    215
    216static const struct st33zp24_phy_ops spi_phy_ops = {
    217	.send = st33zp24_spi_send,
    218	.recv = st33zp24_spi_recv,
    219};
    220
    221static const struct acpi_gpio_params lpcpd_gpios = { 1, 0, false };
    222
    223static const struct acpi_gpio_mapping acpi_st33zp24_gpios[] = {
    224	{ "lpcpd-gpios", &lpcpd_gpios, 1 },
    225	{},
    226};
    227
    228static int st33zp24_spi_acpi_request_resources(struct spi_device *spi_dev)
    229{
    230	struct tpm_chip *chip = spi_get_drvdata(spi_dev);
    231	struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
    232	struct st33zp24_spi_phy *phy = tpm_dev->phy_id;
    233	struct gpio_desc *gpiod_lpcpd;
    234	struct device *dev = &spi_dev->dev;
    235	int ret;
    236
    237	ret = devm_acpi_dev_add_driver_gpios(dev, acpi_st33zp24_gpios);
    238	if (ret)
    239		return ret;
    240
    241	/* Get LPCPD GPIO from ACPI */
    242	gpiod_lpcpd = devm_gpiod_get(dev, "lpcpd", GPIOD_OUT_HIGH);
    243	if (IS_ERR(gpiod_lpcpd)) {
    244		dev_err(dev, "Failed to retrieve lpcpd-gpios from acpi.\n");
    245		phy->io_lpcpd = -1;
    246		/*
    247		 * lpcpd pin is not specified. This is not an issue as
    248		 * power management can be also managed by TPM specific
    249		 * commands. So leave with a success status code.
    250		 */
    251		return 0;
    252	}
    253
    254	phy->io_lpcpd = desc_to_gpio(gpiod_lpcpd);
    255
    256	return 0;
    257}
    258
    259static int st33zp24_spi_of_request_resources(struct spi_device *spi_dev)
    260{
    261	struct tpm_chip *chip = spi_get_drvdata(spi_dev);
    262	struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
    263	struct st33zp24_spi_phy *phy = tpm_dev->phy_id;
    264	struct device_node *pp;
    265	int gpio;
    266	int ret;
    267
    268	pp = spi_dev->dev.of_node;
    269	if (!pp) {
    270		dev_err(&spi_dev->dev, "No platform data\n");
    271		return -ENODEV;
    272	}
    273
    274	/* Get GPIO from device tree */
    275	gpio = of_get_named_gpio(pp, "lpcpd-gpios", 0);
    276	if (gpio < 0) {
    277		dev_err(&spi_dev->dev,
    278			"Failed to retrieve lpcpd-gpios from dts.\n");
    279		phy->io_lpcpd = -1;
    280		/*
    281		 * lpcpd pin is not specified. This is not an issue as
    282		 * power management can be also managed by TPM specific
    283		 * commands. So leave with a success status code.
    284		 */
    285		return 0;
    286	}
    287	/* GPIO request and configuration */
    288	ret = devm_gpio_request_one(&spi_dev->dev, gpio,
    289			GPIOF_OUT_INIT_HIGH, "TPM IO LPCPD");
    290	if (ret) {
    291		dev_err(&spi_dev->dev, "Failed to request lpcpd pin\n");
    292		return -ENODEV;
    293	}
    294	phy->io_lpcpd = gpio;
    295
    296	return 0;
    297}
    298
    299static int st33zp24_spi_request_resources(struct spi_device *dev)
    300{
    301	struct tpm_chip *chip = spi_get_drvdata(dev);
    302	struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
    303	struct st33zp24_spi_phy *phy = tpm_dev->phy_id;
    304	struct st33zp24_platform_data *pdata;
    305	int ret;
    306
    307	pdata = dev->dev.platform_data;
    308	if (!pdata) {
    309		dev_err(&dev->dev, "No platform data\n");
    310		return -ENODEV;
    311	}
    312
    313	/* store for late use */
    314	phy->io_lpcpd = pdata->io_lpcpd;
    315
    316	if (gpio_is_valid(pdata->io_lpcpd)) {
    317		ret = devm_gpio_request_one(&dev->dev,
    318				pdata->io_lpcpd, GPIOF_OUT_INIT_HIGH,
    319				"TPM IO_LPCPD");
    320		if (ret) {
    321			dev_err(&dev->dev, "%s : reset gpio_request failed\n",
    322				__FILE__);
    323			return ret;
    324		}
    325	}
    326
    327	return 0;
    328}
    329
    330/*
    331 * st33zp24_spi_probe initialize the TPM device
    332 * @param: dev, the spi_device description (TPM SPI description).
    333 * @return: 0 in case of success.
    334 *	 or a negative value describing the error.
    335 */
    336static int st33zp24_spi_probe(struct spi_device *dev)
    337{
    338	int ret;
    339	struct st33zp24_platform_data *pdata;
    340	struct st33zp24_spi_phy *phy;
    341
    342	/* Check SPI platform functionnalities */
    343	if (!dev) {
    344		pr_info("%s: dev is NULL. Device is not accessible.\n",
    345			__func__);
    346		return -ENODEV;
    347	}
    348
    349	phy = devm_kzalloc(&dev->dev, sizeof(struct st33zp24_spi_phy),
    350			   GFP_KERNEL);
    351	if (!phy)
    352		return -ENOMEM;
    353
    354	phy->spi_device = dev;
    355
    356	pdata = dev->dev.platform_data;
    357	if (!pdata && dev->dev.of_node) {
    358		ret = st33zp24_spi_of_request_resources(dev);
    359		if (ret)
    360			return ret;
    361	} else if (pdata) {
    362		ret = st33zp24_spi_request_resources(dev);
    363		if (ret)
    364			return ret;
    365	} else if (ACPI_HANDLE(&dev->dev)) {
    366		ret = st33zp24_spi_acpi_request_resources(dev);
    367		if (ret)
    368			return ret;
    369	}
    370
    371	phy->latency = st33zp24_spi_evaluate_latency(phy);
    372	if (phy->latency <= 0)
    373		return -ENODEV;
    374
    375	return st33zp24_probe(phy, &spi_phy_ops, &dev->dev, dev->irq,
    376			      phy->io_lpcpd);
    377}
    378
    379/*
    380 * st33zp24_spi_remove remove the TPM device
    381 * @param: client, the spi_device description (TPM SPI description).
    382 * @return: 0 in case of success.
    383 */
    384static void st33zp24_spi_remove(struct spi_device *dev)
    385{
    386	struct tpm_chip *chip = spi_get_drvdata(dev);
    387
    388	st33zp24_remove(chip);
    389}
    390
    391static const struct spi_device_id st33zp24_spi_id[] = {
    392	{TPM_ST33_SPI, 0},
    393	{}
    394};
    395MODULE_DEVICE_TABLE(spi, st33zp24_spi_id);
    396
    397static const struct of_device_id of_st33zp24_spi_match[] = {
    398	{ .compatible = "st,st33zp24-spi", },
    399	{}
    400};
    401MODULE_DEVICE_TABLE(of, of_st33zp24_spi_match);
    402
    403static const struct acpi_device_id st33zp24_spi_acpi_match[] = {
    404	{"SMO3324"},
    405	{}
    406};
    407MODULE_DEVICE_TABLE(acpi, st33zp24_spi_acpi_match);
    408
    409static SIMPLE_DEV_PM_OPS(st33zp24_spi_ops, st33zp24_pm_suspend,
    410			 st33zp24_pm_resume);
    411
    412static struct spi_driver st33zp24_spi_driver = {
    413	.driver = {
    414		.name = TPM_ST33_SPI,
    415		.pm = &st33zp24_spi_ops,
    416		.of_match_table = of_match_ptr(of_st33zp24_spi_match),
    417		.acpi_match_table = ACPI_PTR(st33zp24_spi_acpi_match),
    418	},
    419	.probe = st33zp24_spi_probe,
    420	.remove = st33zp24_spi_remove,
    421	.id_table = st33zp24_spi_id,
    422};
    423
    424module_spi_driver(st33zp24_spi_driver);
    425
    426MODULE_AUTHOR("TPM support (TPMsupport@list.st.com)");
    427MODULE_DESCRIPTION("STM TPM 1.2 SPI ST33 Driver");
    428MODULE_VERSION("1.3.0");
    429MODULE_LICENSE("GPL");