root/drivers/char/tpm/st33zp24/spi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. st33zp24_status_to_errno
  2. st33zp24_spi_send
  3. st33zp24_spi_read8_reg
  4. st33zp24_spi_recv
  5. st33zp24_spi_evaluate_latency
  6. st33zp24_spi_acpi_request_resources
  7. st33zp24_spi_of_request_resources
  8. st33zp24_spi_request_resources
  9. st33zp24_spi_probe
  10. st33zp24_spi_remove

   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 
  58 struct 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 
  68 static 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  */
 101 static 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  */
 144 static 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  */
 185 static 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 
 196 static 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 
 216 static const struct st33zp24_phy_ops spi_phy_ops = {
 217         .send = st33zp24_spi_send,
 218         .recv = st33zp24_spi_recv,
 219 };
 220 
 221 static const struct acpi_gpio_params lpcpd_gpios = { 1, 0, false };
 222 
 223 static const struct acpi_gpio_mapping acpi_st33zp24_gpios[] = {
 224         { "lpcpd-gpios", &lpcpd_gpios, 1 },
 225         {},
 226 };
 227 
 228 static 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 
 259 static 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 
 299 static 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 drescription (TPM SPI description).
 333  * @return: 0 in case of success.
 334  *       or a negative value describing the error.
 335  */
 336 static 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 drescription (TPM SPI description).
 382  * @return: 0 in case of success.
 383  */
 384 static 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 
 396 static const struct spi_device_id st33zp24_spi_id[] = {
 397         {TPM_ST33_SPI, 0},
 398         {}
 399 };
 400 MODULE_DEVICE_TABLE(spi, st33zp24_spi_id);
 401 
 402 static const struct of_device_id of_st33zp24_spi_match[] = {
 403         { .compatible = "st,st33zp24-spi", },
 404         {}
 405 };
 406 MODULE_DEVICE_TABLE(of, of_st33zp24_spi_match);
 407 
 408 static const struct acpi_device_id st33zp24_spi_acpi_match[] = {
 409         {"SMO3324"},
 410         {}
 411 };
 412 MODULE_DEVICE_TABLE(acpi, st33zp24_spi_acpi_match);
 413 
 414 static SIMPLE_DEV_PM_OPS(st33zp24_spi_ops, st33zp24_pm_suspend,
 415                          st33zp24_pm_resume);
 416 
 417 static 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 
 429 module_spi_driver(st33zp24_spi_driver);
 430 
 431 MODULE_AUTHOR("TPM support (TPMsupport@list.st.com)");
 432 MODULE_DESCRIPTION("STM TPM 1.2 SPI ST33 Driver");
 433 MODULE_VERSION("1.3.0");
 434 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */