linux/drivers/char/tpm/st33zp24/spi.c
<<
>>
Prefs
   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 int st33zp24_spi_remove(struct spi_device *dev)
 385{
 386        struct tpm_chip *chip = spi_get_drvdata(dev);
 387        int ret;
 388
 389        ret = st33zp24_remove(chip);
 390        if (ret)
 391                return ret;
 392
 393        return 0;
 394}
 395
 396static const struct spi_device_id st33zp24_spi_id[] = {
 397        {TPM_ST33_SPI, 0},
 398        {}
 399};
 400MODULE_DEVICE_TABLE(spi, st33zp24_spi_id);
 401
 402static const struct of_device_id of_st33zp24_spi_match[] = {
 403        { .compatible = "st,st33zp24-spi", },
 404        {}
 405};
 406MODULE_DEVICE_TABLE(of, of_st33zp24_spi_match);
 407
 408static const struct acpi_device_id st33zp24_spi_acpi_match[] = {
 409        {"SMO3324"},
 410        {}
 411};
 412MODULE_DEVICE_TABLE(acpi, st33zp24_spi_acpi_match);
 413
 414static SIMPLE_DEV_PM_OPS(st33zp24_spi_ops, st33zp24_pm_suspend,
 415                         st33zp24_pm_resume);
 416
 417static struct spi_driver st33zp24_spi_driver = {
 418        .driver = {
 419                .name = TPM_ST33_SPI,
 420                .pm = &st33zp24_spi_ops,
 421                .of_match_table = of_match_ptr(of_st33zp24_spi_match),
 422                .acpi_match_table = ACPI_PTR(st33zp24_spi_acpi_match),
 423        },
 424        .probe = st33zp24_spi_probe,
 425        .remove = st33zp24_spi_remove,
 426        .id_table = st33zp24_spi_id,
 427};
 428
 429module_spi_driver(st33zp24_spi_driver);
 430
 431MODULE_AUTHOR("TPM support (TPMsupport@list.st.com)");
 432MODULE_DESCRIPTION("STM TPM 1.2 SPI ST33 Driver");
 433MODULE_VERSION("1.3.0");
 434MODULE_LICENSE("GPL");
 435