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