Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
0004  * Copyright (C) 2009 - 2016 STMicroelectronics
0005  */
0006 
0007 #include <linux/module.h>
0008 #include <linux/i2c.h>
0009 #include <linux/gpio.h>
0010 #include <linux/gpio/consumer.h>
0011 #include <linux/of_irq.h>
0012 #include <linux/of_gpio.h>
0013 #include <linux/acpi.h>
0014 #include <linux/tpm.h>
0015 #include <linux/platform_data/st33zp24.h>
0016 
0017 #include "../tpm.h"
0018 #include "st33zp24.h"
0019 
0020 #define TPM_DUMMY_BYTE          0xAA
0021 
0022 struct st33zp24_i2c_phy {
0023     struct i2c_client *client;
0024     u8 buf[ST33ZP24_BUFSIZE + 1];
0025     int io_lpcpd;
0026 };
0027 
0028 /*
0029  * write8_reg
0030  * Send byte to the TIS register according to the ST33ZP24 I2C protocol.
0031  * @param: tpm_register, the tpm tis register where the data should be written
0032  * @param: tpm_data, the tpm_data to write inside the tpm_register
0033  * @param: tpm_size, The length of the data
0034  * @return: Returns negative errno, or else the number of bytes written.
0035  */
0036 static int write8_reg(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size)
0037 {
0038     struct st33zp24_i2c_phy *phy = phy_id;
0039 
0040     phy->buf[0] = tpm_register;
0041     memcpy(phy->buf + 1, tpm_data, tpm_size);
0042     return i2c_master_send(phy->client, phy->buf, tpm_size + 1);
0043 } /* write8_reg() */
0044 
0045 /*
0046  * read8_reg
0047  * Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
0048  * @param: tpm_register, the tpm tis register where the data should be read
0049  * @param: tpm_data, the TPM response
0050  * @param: tpm_size, tpm TPM response size to read.
0051  * @return: number of byte read successfully: should be one if success.
0052  */
0053 static int read8_reg(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size)
0054 {
0055     struct st33zp24_i2c_phy *phy = phy_id;
0056     u8 status = 0;
0057     u8 data;
0058 
0059     data = TPM_DUMMY_BYTE;
0060     status = write8_reg(phy, tpm_register, &data, 1);
0061     if (status == 2)
0062         status = i2c_master_recv(phy->client, tpm_data, tpm_size);
0063     return status;
0064 } /* read8_reg() */
0065 
0066 /*
0067  * st33zp24_i2c_send
0068  * Send byte to the TIS register according to the ST33ZP24 I2C protocol.
0069  * @param: phy_id, the phy description
0070  * @param: tpm_register, the tpm tis register where the data should be written
0071  * @param: tpm_data, the tpm_data to write inside the tpm_register
0072  * @param: tpm_size, the length of the data
0073  * @return: number of byte written successfully: should be one if success.
0074  */
0075 static int st33zp24_i2c_send(void *phy_id, u8 tpm_register, u8 *tpm_data,
0076                  int tpm_size)
0077 {
0078     return write8_reg(phy_id, tpm_register | TPM_WRITE_DIRECTION, tpm_data,
0079               tpm_size);
0080 }
0081 
0082 /*
0083  * st33zp24_i2c_recv
0084  * Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
0085  * @param: phy_id, the phy description
0086  * @param: tpm_register, the tpm tis register where the data should be read
0087  * @param: tpm_data, the TPM response
0088  * @param: tpm_size, tpm TPM response size to read.
0089  * @return: number of byte read successfully: should be one if success.
0090  */
0091 static int st33zp24_i2c_recv(void *phy_id, u8 tpm_register, u8 *tpm_data,
0092                  int tpm_size)
0093 {
0094     return read8_reg(phy_id, tpm_register, tpm_data, tpm_size);
0095 }
0096 
0097 static const struct st33zp24_phy_ops i2c_phy_ops = {
0098     .send = st33zp24_i2c_send,
0099     .recv = st33zp24_i2c_recv,
0100 };
0101 
0102 static const struct acpi_gpio_params lpcpd_gpios = { 1, 0, false };
0103 
0104 static const struct acpi_gpio_mapping acpi_st33zp24_gpios[] = {
0105     { "lpcpd-gpios", &lpcpd_gpios, 1 },
0106     {},
0107 };
0108 
0109 static int st33zp24_i2c_acpi_request_resources(struct i2c_client *client)
0110 {
0111     struct tpm_chip *chip = i2c_get_clientdata(client);
0112     struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
0113     struct st33zp24_i2c_phy *phy = tpm_dev->phy_id;
0114     struct gpio_desc *gpiod_lpcpd;
0115     struct device *dev = &client->dev;
0116     int ret;
0117 
0118     ret = devm_acpi_dev_add_driver_gpios(dev, acpi_st33zp24_gpios);
0119     if (ret)
0120         return ret;
0121 
0122     /* Get LPCPD GPIO from ACPI */
0123     gpiod_lpcpd = devm_gpiod_get(dev, "lpcpd", GPIOD_OUT_HIGH);
0124     if (IS_ERR(gpiod_lpcpd)) {
0125         dev_err(&client->dev,
0126             "Failed to retrieve lpcpd-gpios from acpi.\n");
0127         phy->io_lpcpd = -1;
0128         /*
0129          * lpcpd pin is not specified. This is not an issue as
0130          * power management can be also managed by TPM specific
0131          * commands. So leave with a success status code.
0132          */
0133         return 0;
0134     }
0135 
0136     phy->io_lpcpd = desc_to_gpio(gpiod_lpcpd);
0137 
0138     return 0;
0139 }
0140 
0141 static int st33zp24_i2c_of_request_resources(struct i2c_client *client)
0142 {
0143     struct tpm_chip *chip = i2c_get_clientdata(client);
0144     struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
0145     struct st33zp24_i2c_phy *phy = tpm_dev->phy_id;
0146     struct device_node *pp;
0147     int gpio;
0148     int ret;
0149 
0150     pp = client->dev.of_node;
0151     if (!pp) {
0152         dev_err(&client->dev, "No platform data\n");
0153         return -ENODEV;
0154     }
0155 
0156     /* Get GPIO from device tree */
0157     gpio = of_get_named_gpio(pp, "lpcpd-gpios", 0);
0158     if (gpio < 0) {
0159         dev_err(&client->dev,
0160             "Failed to retrieve lpcpd-gpios from dts.\n");
0161         phy->io_lpcpd = -1;
0162         /*
0163          * lpcpd pin is not specified. This is not an issue as
0164          * power management can be also managed by TPM specific
0165          * commands. So leave with a success status code.
0166          */
0167         return 0;
0168     }
0169     /* GPIO request and configuration */
0170     ret = devm_gpio_request_one(&client->dev, gpio,
0171             GPIOF_OUT_INIT_HIGH, "TPM IO LPCPD");
0172     if (ret) {
0173         dev_err(&client->dev, "Failed to request lpcpd pin\n");
0174         return -ENODEV;
0175     }
0176     phy->io_lpcpd = gpio;
0177 
0178     return 0;
0179 }
0180 
0181 static int st33zp24_i2c_request_resources(struct i2c_client *client)
0182 {
0183     struct tpm_chip *chip = i2c_get_clientdata(client);
0184     struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
0185     struct st33zp24_i2c_phy *phy = tpm_dev->phy_id;
0186     struct st33zp24_platform_data *pdata;
0187     int ret;
0188 
0189     pdata = client->dev.platform_data;
0190     if (!pdata) {
0191         dev_err(&client->dev, "No platform data\n");
0192         return -ENODEV;
0193     }
0194 
0195     /* store for late use */
0196     phy->io_lpcpd = pdata->io_lpcpd;
0197 
0198     if (gpio_is_valid(pdata->io_lpcpd)) {
0199         ret = devm_gpio_request_one(&client->dev,
0200                 pdata->io_lpcpd, GPIOF_OUT_INIT_HIGH,
0201                 "TPM IO_LPCPD");
0202         if (ret) {
0203             dev_err(&client->dev, "Failed to request lpcpd pin\n");
0204             return ret;
0205         }
0206     }
0207 
0208     return 0;
0209 }
0210 
0211 /*
0212  * st33zp24_i2c_probe initialize the TPM device
0213  * @param: client, the i2c_client description (TPM I2C description).
0214  * @param: id, the i2c_device_id struct.
0215  * @return: 0 in case of success.
0216  *   -1 in other case.
0217  */
0218 static int st33zp24_i2c_probe(struct i2c_client *client,
0219                   const struct i2c_device_id *id)
0220 {
0221     int ret;
0222     struct st33zp24_platform_data *pdata;
0223     struct st33zp24_i2c_phy *phy;
0224 
0225     if (!client) {
0226         pr_info("%s: i2c client is NULL. Device not accessible.\n",
0227             __func__);
0228         return -ENODEV;
0229     }
0230 
0231     if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
0232         dev_info(&client->dev, "client not i2c capable\n");
0233         return -ENODEV;
0234     }
0235 
0236     phy = devm_kzalloc(&client->dev, sizeof(struct st33zp24_i2c_phy),
0237                GFP_KERNEL);
0238     if (!phy)
0239         return -ENOMEM;
0240 
0241     phy->client = client;
0242 
0243     pdata = client->dev.platform_data;
0244     if (!pdata && client->dev.of_node) {
0245         ret = st33zp24_i2c_of_request_resources(client);
0246         if (ret)
0247             return ret;
0248     } else if (pdata) {
0249         ret = st33zp24_i2c_request_resources(client);
0250         if (ret)
0251             return ret;
0252     } else if (ACPI_HANDLE(&client->dev)) {
0253         ret = st33zp24_i2c_acpi_request_resources(client);
0254         if (ret)
0255             return ret;
0256     }
0257 
0258     return st33zp24_probe(phy, &i2c_phy_ops, &client->dev, client->irq,
0259                   phy->io_lpcpd);
0260 }
0261 
0262 /*
0263  * st33zp24_i2c_remove remove the TPM device
0264  * @param: client, the i2c_client description (TPM I2C description).
0265  * @return: 0 in case of success.
0266  */
0267 static int st33zp24_i2c_remove(struct i2c_client *client)
0268 {
0269     struct tpm_chip *chip = i2c_get_clientdata(client);
0270 
0271     st33zp24_remove(chip);
0272 
0273     return 0;
0274 }
0275 
0276 static const struct i2c_device_id st33zp24_i2c_id[] = {
0277     {TPM_ST33_I2C, 0},
0278     {}
0279 };
0280 MODULE_DEVICE_TABLE(i2c, st33zp24_i2c_id);
0281 
0282 static const struct of_device_id of_st33zp24_i2c_match[] = {
0283     { .compatible = "st,st33zp24-i2c", },
0284     {}
0285 };
0286 MODULE_DEVICE_TABLE(of, of_st33zp24_i2c_match);
0287 
0288 static const struct acpi_device_id st33zp24_i2c_acpi_match[] = {
0289     {"SMO3324"},
0290     {}
0291 };
0292 MODULE_DEVICE_TABLE(acpi, st33zp24_i2c_acpi_match);
0293 
0294 static SIMPLE_DEV_PM_OPS(st33zp24_i2c_ops, st33zp24_pm_suspend,
0295              st33zp24_pm_resume);
0296 
0297 static struct i2c_driver st33zp24_i2c_driver = {
0298     .driver = {
0299         .name = TPM_ST33_I2C,
0300         .pm = &st33zp24_i2c_ops,
0301         .of_match_table = of_match_ptr(of_st33zp24_i2c_match),
0302         .acpi_match_table = ACPI_PTR(st33zp24_i2c_acpi_match),
0303     },
0304     .probe = st33zp24_i2c_probe,
0305     .remove = st33zp24_i2c_remove,
0306     .id_table = st33zp24_i2c_id
0307 };
0308 
0309 module_i2c_driver(st33zp24_i2c_driver);
0310 
0311 MODULE_AUTHOR("TPM support (TPMsupport@list.st.com)");
0312 MODULE_DESCRIPTION("STM TPM 1.2 I2C ST33 Driver");
0313 MODULE_VERSION("1.3.0");
0314 MODULE_LICENSE("GPL");