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 int st33zp24_spi_acpi_request_resources(struct spi_device *spi_dev)
 234{
 235        struct tpm_chip *chip = spi_get_drvdata(spi_dev);
 236        struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
 237        struct st33zp24_spi_phy *phy = tpm_dev->phy_id;
 238        struct gpio_desc *gpiod_lpcpd;
 239        struct device *dev = &spi_dev->dev;
 240
 241        /* Get LPCPD GPIO from ACPI */
 242        gpiod_lpcpd = devm_gpiod_get_index(dev, "TPM IO LPCPD", 1,
 243                                           GPIOD_OUT_HIGH);
 244        if (IS_ERR(gpiod_lpcpd)) {
 245                dev_err(dev, "Failed to retrieve lpcpd-gpios from acpi.\n");
 246                phy->io_lpcpd = -1;
 247                /*
 248                 * lpcpd pin is not specified. This is not an issue as
 249                 * power management can be also managed by TPM specific
 250                 * commands. So leave with a success status code.
 251                 */
 252                return 0;
 253        }
 254
 255        phy->io_lpcpd = desc_to_gpio(gpiod_lpcpd);
 256
 257        return 0;
 258}
 259
 260static int st33zp24_spi_of_request_resources(struct spi_device *spi_dev)
 261{
 262        struct tpm_chip *chip = spi_get_drvdata(spi_dev);
 263        struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
 264        struct st33zp24_spi_phy *phy = tpm_dev->phy_id;
 265        struct device_node *pp;
 266        int gpio;
 267        int ret;
 268
 269        pp = spi_dev->dev.of_node;
 270        if (!pp) {
 271                dev_err(&spi_dev->dev, "No platform data\n");
 272                return -ENODEV;
 273        }
 274
 275        /* Get GPIO from device tree */
 276        gpio = of_get_named_gpio(pp, "lpcpd-gpios", 0);
 277        if (gpio < 0) {
 278                dev_err(&spi_dev->dev,
 279                        "Failed to retrieve lpcpd-gpios from dts.\n");
 280                phy->io_lpcpd = -1;
 281                /*
 282                 * lpcpd pin is not specified. This is not an issue as
 283                 * power management can be also managed by TPM specific
 284                 * commands. So leave with a success status code.
 285                 */
 286                return 0;
 287        }
 288        /* GPIO request and configuration */
 289        ret = devm_gpio_request_one(&spi_dev->dev, gpio,
 290                        GPIOF_OUT_INIT_HIGH, "TPM IO LPCPD");
 291        if (ret) {
 292                dev_err(&spi_dev->dev, "Failed to request lpcpd pin\n");
 293                return -ENODEV;
 294        }
 295        phy->io_lpcpd = gpio;
 296
 297        return 0;
 298}
 299
 300static int st33zp24_spi_request_resources(struct spi_device *dev)
 301{
 302        struct tpm_chip *chip = spi_get_drvdata(dev);
 303        struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
 304        struct st33zp24_spi_phy *phy = tpm_dev->phy_id;
 305        struct st33zp24_platform_data *pdata;
 306        int ret;
 307
 308        pdata = dev->dev.platform_data;
 309        if (!pdata) {
 310                dev_err(&dev->dev, "No platform data\n");
 311                return -ENODEV;
 312        }
 313
 314        /* store for late use */
 315        phy->io_lpcpd = pdata->io_lpcpd;
 316
 317        if (gpio_is_valid(pdata->io_lpcpd)) {
 318                ret = devm_gpio_request_one(&dev->dev,
 319                                pdata->io_lpcpd, GPIOF_OUT_INIT_HIGH,
 320                                "TPM IO_LPCPD");
 321                if (ret) {
 322                        dev_err(&dev->dev, "%s : reset gpio_request failed\n",
 323                                __FILE__);
 324                        return ret;
 325                }
 326        }
 327
 328        return 0;
 329}
 330
 331/*
 332 * st33zp24_spi_probe initialize the TPM device
 333 * @param: dev, the spi_device drescription (TPM SPI description).
 334 * @return: 0 in case of success.
 335 *       or a negative value describing the error.
 336 */
 337static int st33zp24_spi_probe(struct spi_device *dev)
 338{
 339        int ret;
 340        struct st33zp24_platform_data *pdata;
 341        struct st33zp24_spi_phy *phy;
 342
 343        /* Check SPI platform functionnalities */
 344        if (!dev) {
 345                pr_info("%s: dev is NULL. Device is not accessible.\n",
 346                        __func__);
 347                return -ENODEV;
 348        }
 349
 350        phy = devm_kzalloc(&dev->dev, sizeof(struct st33zp24_spi_phy),
 351                           GFP_KERNEL);
 352        if (!phy)
 353                return -ENOMEM;
 354
 355        phy->spi_device = dev;
 356
 357        pdata = dev->dev.platform_data;
 358        if (!pdata && dev->dev.of_node) {
 359                ret = st33zp24_spi_of_request_resources(dev);
 360                if (ret)
 361                        return ret;
 362        } else if (pdata) {
 363                ret = st33zp24_spi_request_resources(dev);
 364                if (ret)
 365                        return ret;
 366        } else if (ACPI_HANDLE(&dev->dev)) {
 367                ret = st33zp24_spi_acpi_request_resources(dev);
 368                if (ret)
 369                        return ret;
 370        }
 371
 372        phy->latency = st33zp24_spi_evaluate_latency(phy);
 373        if (phy->latency <= 0)
 374                return -ENODEV;
 375
 376        return st33zp24_probe(phy, &spi_phy_ops, &dev->dev, dev->irq,
 377                              phy->io_lpcpd);
 378}
 379
 380/*
 381 * st33zp24_spi_remove remove the TPM device
 382 * @param: client, the spi_device drescription (TPM SPI description).
 383 * @return: 0 in case of success.
 384 */
 385static int st33zp24_spi_remove(struct spi_device *dev)
 386{
 387        struct tpm_chip *chip = spi_get_drvdata(dev);
 388
 389        return st33zp24_remove(chip);
 390}
 391
 392static const struct spi_device_id st33zp24_spi_id[] = {
 393        {TPM_ST33_SPI, 0},
 394        {}
 395};
 396MODULE_DEVICE_TABLE(spi, st33zp24_spi_id);
 397
 398static const struct of_device_id of_st33zp24_spi_match[] = {
 399        { .compatible = "st,st33zp24-spi", },
 400        {}
 401};
 402MODULE_DEVICE_TABLE(of, of_st33zp24_spi_match);
 403
 404static const struct acpi_device_id st33zp24_spi_acpi_match[] = {
 405        {"SMO3324"},
 406        {}
 407};
 408MODULE_DEVICE_TABLE(acpi, st33zp24_spi_acpi_match);
 409
 410static SIMPLE_DEV_PM_OPS(st33zp24_spi_ops, st33zp24_pm_suspend,
 411                         st33zp24_pm_resume);
 412
 413static struct spi_driver st33zp24_spi_driver = {
 414        .driver = {
 415                .name = TPM_ST33_SPI,
 416                .pm = &st33zp24_spi_ops,
 417                .of_match_table = of_match_ptr(of_st33zp24_spi_match),
 418                .acpi_match_table = ACPI_PTR(st33zp24_spi_acpi_match),
 419        },
 420        .probe = st33zp24_spi_probe,
 421        .remove = st33zp24_spi_remove,
 422        .id_table = st33zp24_spi_id,
 423};
 424
 425module_spi_driver(st33zp24_spi_driver);
 426
 427MODULE_AUTHOR("TPM support (TPMsupport@list.st.com)");
 428MODULE_DESCRIPTION("STM TPM 1.2 SPI ST33 Driver");
 429MODULE_VERSION("1.3.0");
 430MODULE_LICENSE("GPL");
 431