i2c.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
  4. * Copyright (C) 2009 - 2016 STMicroelectronics
  5. */
  6. #include <linux/module.h>
  7. #include <linux/i2c.h>
  8. #include <linux/of.h>
  9. #include <linux/acpi.h>
  10. #include <linux/tpm.h>
  11. #include "../tpm.h"
  12. #include "st33zp24.h"
  13. #define TPM_DUMMY_BYTE 0xAA
  14. struct st33zp24_i2c_phy {
  15. struct i2c_client *client;
  16. u8 buf[ST33ZP24_BUFSIZE + 1];
  17. };
  18. /*
  19. * write8_reg
  20. * Send byte to the TIS register according to the ST33ZP24 I2C protocol.
  21. * @param: tpm_register, the tpm tis register where the data should be written
  22. * @param: tpm_data, the tpm_data to write inside the tpm_register
  23. * @param: tpm_size, The length of the data
  24. * @return: Returns negative errno, or else the number of bytes written.
  25. */
  26. static int write8_reg(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size)
  27. {
  28. struct st33zp24_i2c_phy *phy = phy_id;
  29. phy->buf[0] = tpm_register;
  30. memcpy(phy->buf + 1, tpm_data, tpm_size);
  31. return i2c_master_send(phy->client, phy->buf, tpm_size + 1);
  32. } /* write8_reg() */
  33. /*
  34. * read8_reg
  35. * Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
  36. * @param: tpm_register, the tpm tis register where the data should be read
  37. * @param: tpm_data, the TPM response
  38. * @param: tpm_size, tpm TPM response size to read.
  39. * @return: number of byte read successfully: should be one if success.
  40. */
  41. static int read8_reg(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size)
  42. {
  43. struct st33zp24_i2c_phy *phy = phy_id;
  44. u8 status = 0;
  45. u8 data;
  46. data = TPM_DUMMY_BYTE;
  47. status = write8_reg(phy, tpm_register, &data, 1);
  48. if (status == 2)
  49. status = i2c_master_recv(phy->client, tpm_data, tpm_size);
  50. return status;
  51. } /* read8_reg() */
  52. /*
  53. * st33zp24_i2c_send
  54. * Send byte to the TIS register according to the ST33ZP24 I2C protocol.
  55. * @param: phy_id, the phy description
  56. * @param: tpm_register, the tpm tis register where the data should be written
  57. * @param: tpm_data, the tpm_data to write inside the tpm_register
  58. * @param: tpm_size, the length of the data
  59. * @return: number of byte written successfully: should be one if success.
  60. */
  61. static int st33zp24_i2c_send(void *phy_id, u8 tpm_register, u8 *tpm_data,
  62. int tpm_size)
  63. {
  64. return write8_reg(phy_id, tpm_register | TPM_WRITE_DIRECTION, tpm_data,
  65. tpm_size);
  66. }
  67. /*
  68. * st33zp24_i2c_recv
  69. * Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
  70. * @param: phy_id, the phy description
  71. * @param: tpm_register, the tpm tis register where the data should be read
  72. * @param: tpm_data, the TPM response
  73. * @param: tpm_size, tpm TPM response size to read.
  74. * @return: number of byte read successfully: should be one if success.
  75. */
  76. static int st33zp24_i2c_recv(void *phy_id, u8 tpm_register, u8 *tpm_data,
  77. int tpm_size)
  78. {
  79. return read8_reg(phy_id, tpm_register, tpm_data, tpm_size);
  80. }
  81. static const struct st33zp24_phy_ops i2c_phy_ops = {
  82. .send = st33zp24_i2c_send,
  83. .recv = st33zp24_i2c_recv,
  84. };
  85. /*
  86. * st33zp24_i2c_probe initialize the TPM device
  87. * @param: client, the i2c_client description (TPM I2C description).
  88. * @param: id, the i2c_device_id struct.
  89. * @return: 0 in case of success.
  90. * -1 in other case.
  91. */
  92. static int st33zp24_i2c_probe(struct i2c_client *client)
  93. {
  94. struct st33zp24_i2c_phy *phy;
  95. if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
  96. dev_info(&client->dev, "client not i2c capable\n");
  97. return -ENODEV;
  98. }
  99. phy = devm_kzalloc(&client->dev, sizeof(struct st33zp24_i2c_phy),
  100. GFP_KERNEL);
  101. if (!phy)
  102. return -ENOMEM;
  103. phy->client = client;
  104. return st33zp24_probe(phy, &i2c_phy_ops, &client->dev, client->irq);
  105. }
  106. /*
  107. * st33zp24_i2c_remove remove the TPM device
  108. * @param: client, the i2c_client description (TPM I2C description).
  109. * @return: 0 in case of success.
  110. */
  111. static void st33zp24_i2c_remove(struct i2c_client *client)
  112. {
  113. struct tpm_chip *chip = i2c_get_clientdata(client);
  114. st33zp24_remove(chip);
  115. }
  116. static const struct i2c_device_id st33zp24_i2c_id[] = {
  117. { TPM_ST33_I2C },
  118. {}
  119. };
  120. MODULE_DEVICE_TABLE(i2c, st33zp24_i2c_id);
  121. static const struct of_device_id of_st33zp24_i2c_match[] __maybe_unused = {
  122. { .compatible = "st,st33zp24-i2c", },
  123. {}
  124. };
  125. MODULE_DEVICE_TABLE(of, of_st33zp24_i2c_match);
  126. static const struct acpi_device_id st33zp24_i2c_acpi_match[] __maybe_unused = {
  127. {"SMO3324"},
  128. {}
  129. };
  130. MODULE_DEVICE_TABLE(acpi, st33zp24_i2c_acpi_match);
  131. static SIMPLE_DEV_PM_OPS(st33zp24_i2c_ops, st33zp24_pm_suspend,
  132. st33zp24_pm_resume);
  133. static struct i2c_driver st33zp24_i2c_driver = {
  134. .driver = {
  135. .name = TPM_ST33_I2C,
  136. .pm = &st33zp24_i2c_ops,
  137. .of_match_table = of_match_ptr(of_st33zp24_i2c_match),
  138. .acpi_match_table = ACPI_PTR(st33zp24_i2c_acpi_match),
  139. },
  140. .probe = st33zp24_i2c_probe,
  141. .remove = st33zp24_i2c_remove,
  142. .id_table = st33zp24_i2c_id
  143. };
  144. module_i2c_driver(st33zp24_i2c_driver);
  145. MODULE_AUTHOR("TPM support <TPMsupport@list.st.com>");
  146. MODULE_DESCRIPTION("STM TPM 1.2 I2C ST33 Driver");
  147. MODULE_VERSION("1.3.0");
  148. MODULE_LICENSE("GPL");