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