diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-10-20 00:10:27 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-10-20 00:10:27 -0300 |
commit | d0b2f91bede3bd5e3d24dd6803e56eee959c1797 (patch) | |
tree | 7fee4ab0509879c373c4f2cbd5b8a5be5b4041ee /drivers/char/tpm/st33zp24 | |
parent | e914f8eb445e8f74b00303c19c2ffceaedd16a05 (diff) |
Linux-libre 4.8.2-gnupck-4.8.2-gnu
Diffstat (limited to 'drivers/char/tpm/st33zp24')
-rw-r--r-- | drivers/char/tpm/st33zp24/Kconfig | 11 | ||||
-rw-r--r-- | drivers/char/tpm/st33zp24/i2c.c | 70 | ||||
-rw-r--r-- | drivers/char/tpm/st33zp24/spi.c | 184 | ||||
-rw-r--r-- | drivers/char/tpm/st33zp24/st33zp24.c | 129 | ||||
-rw-r--r-- | drivers/char/tpm/st33zp24/st33zp24.h | 14 |
5 files changed, 229 insertions, 179 deletions
diff --git a/drivers/char/tpm/st33zp24/Kconfig b/drivers/char/tpm/st33zp24/Kconfig index 19c007461..e74c6f29f 100644 --- a/drivers/char/tpm/st33zp24/Kconfig +++ b/drivers/char/tpm/st33zp24/Kconfig @@ -1,6 +1,5 @@ config TCG_TIS_ST33ZP24 - tristate "STMicroelectronics TPM Interface Specification 1.2 Interface" - depends on GPIOLIB || COMPILE_TEST + tristate ---help--- STMicroelectronics ST33ZP24 core driver. It implements the core TPM1.2 logic and hooks into the TPM kernel APIs. Physical layers will @@ -10,9 +9,9 @@ config TCG_TIS_ST33ZP24 tpm_st33zp24. config TCG_TIS_ST33ZP24_I2C - tristate "TPM 1.2 ST33ZP24 I2C support" - depends on TCG_TIS_ST33ZP24 + tristate "STMicroelectronics TPM Interface Specification 1.2 Interface (I2C)" depends on I2C + select TCG_TIS_ST33ZP24 ---help--- This module adds support for the STMicroelectronics TPM security chip ST33ZP24 with i2c interface. @@ -20,9 +19,9 @@ config TCG_TIS_ST33ZP24_I2C called tpm_st33zp24_i2c. config TCG_TIS_ST33ZP24_SPI - tristate "TPM 1.2 ST33ZP24 SPI support" - depends on TCG_TIS_ST33ZP24 + tristate "STMicroelectronics TPM Interface Specification 1.2 Interface (SPI)" depends on SPI + select TCG_TIS_ST33ZP24 ---help--- This module adds support for the STMicroelectronics TPM security chip ST33ZP24 with spi interface. diff --git a/drivers/char/tpm/st33zp24/i2c.c b/drivers/char/tpm/st33zp24/i2c.c index 309d2767c..028a9cd76 100644 --- a/drivers/char/tpm/st33zp24/i2c.c +++ b/drivers/char/tpm/st33zp24/i2c.c @@ -1,6 +1,6 @@ /* * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24 - * Copyright (C) 2009 - 2015 STMicroelectronics + * Copyright (C) 2009 - 2016 STMicroelectronics * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,11 +19,14 @@ #include <linux/module.h> #include <linux/i2c.h> #include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/of_irq.h> #include <linux/of_gpio.h> +#include <linux/acpi.h> #include <linux/tpm.h> #include <linux/platform_data/st33zp24.h> +#include "../tpm.h" #include "st33zp24.h" #define TPM_DUMMY_BYTE 0xAA @@ -108,11 +111,40 @@ static const struct st33zp24_phy_ops i2c_phy_ops = { .recv = st33zp24_i2c_recv, }; -#ifdef CONFIG_OF -static int st33zp24_i2c_of_request_resources(struct st33zp24_i2c_phy *phy) +static int st33zp24_i2c_acpi_request_resources(struct i2c_client *client) { + struct tpm_chip *chip = i2c_get_clientdata(client); + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); + struct st33zp24_i2c_phy *phy = tpm_dev->phy_id; + struct gpio_desc *gpiod_lpcpd; + struct device *dev = &client->dev; + + /* Get LPCPD GPIO from ACPI */ + gpiod_lpcpd = devm_gpiod_get_index(dev, "TPM IO LPCPD", 1, + GPIOD_OUT_HIGH); + if (IS_ERR(gpiod_lpcpd)) { + dev_err(&client->dev, + "Failed to retrieve lpcpd-gpios from acpi.\n"); + phy->io_lpcpd = -1; + /* + * lpcpd pin is not specified. This is not an issue as + * power management can be also managed by TPM specific + * commands. So leave with a success status code. + */ + return 0; + } + + phy->io_lpcpd = desc_to_gpio(gpiod_lpcpd); + + return 0; +} + +static int st33zp24_i2c_of_request_resources(struct i2c_client *client) +{ + struct tpm_chip *chip = i2c_get_clientdata(client); + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); + struct st33zp24_i2c_phy *phy = tpm_dev->phy_id; struct device_node *pp; - struct i2c_client *client = phy->client; int gpio; int ret; @@ -146,16 +178,12 @@ static int st33zp24_i2c_of_request_resources(struct st33zp24_i2c_phy *phy) return 0; } -#else -static int st33zp24_i2c_of_request_resources(struct st33zp24_i2c_phy *phy) -{ - return -ENODEV; -} -#endif -static int st33zp24_i2c_request_resources(struct i2c_client *client, - struct st33zp24_i2c_phy *phy) +static int st33zp24_i2c_request_resources(struct i2c_client *client) { + struct tpm_chip *chip = i2c_get_clientdata(client); + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); + struct st33zp24_i2c_phy *phy = tpm_dev->phy_id; struct st33zp24_platform_data *pdata; int ret; @@ -212,13 +240,18 @@ static int st33zp24_i2c_probe(struct i2c_client *client, return -ENOMEM; phy->client = client; + pdata = client->dev.platform_data; if (!pdata && client->dev.of_node) { - ret = st33zp24_i2c_of_request_resources(phy); + ret = st33zp24_i2c_of_request_resources(client); if (ret) return ret; } else if (pdata) { - ret = st33zp24_i2c_request_resources(client, phy); + ret = st33zp24_i2c_request_resources(client); + if (ret) + return ret; + } else if (ACPI_HANDLE(&client->dev)) { + ret = st33zp24_i2c_acpi_request_resources(client); if (ret) return ret; } @@ -245,13 +278,17 @@ static const struct i2c_device_id st33zp24_i2c_id[] = { }; MODULE_DEVICE_TABLE(i2c, st33zp24_i2c_id); -#ifdef CONFIG_OF static const struct of_device_id of_st33zp24_i2c_match[] = { { .compatible = "st,st33zp24-i2c", }, {} }; MODULE_DEVICE_TABLE(of, of_st33zp24_i2c_match); -#endif + +static const struct acpi_device_id st33zp24_i2c_acpi_match[] = { + {"SMO3324"}, + {} +}; +MODULE_DEVICE_TABLE(acpi, st33zp24_i2c_acpi_match); static SIMPLE_DEV_PM_OPS(st33zp24_i2c_ops, st33zp24_pm_suspend, st33zp24_pm_resume); @@ -261,6 +298,7 @@ static struct i2c_driver st33zp24_i2c_driver = { .name = TPM_ST33_I2C, .pm = &st33zp24_i2c_ops, .of_match_table = of_match_ptr(of_st33zp24_i2c_match), + .acpi_match_table = ACPI_PTR(st33zp24_i2c_acpi_match), }, .probe = st33zp24_i2c_probe, .remove = st33zp24_i2c_remove, diff --git a/drivers/char/tpm/st33zp24/spi.c b/drivers/char/tpm/st33zp24/spi.c index f974c945c..9f5a01170 100644 --- a/drivers/char/tpm/st33zp24/spi.c +++ b/drivers/char/tpm/st33zp24/spi.c @@ -1,6 +1,6 @@ /* * STMicroelectronics TPM SPI Linux driver for TPM ST33ZP24 - * Copyright (C) 2009 - 2015 STMicroelectronics + * Copyright (C) 2009 - 2016 STMicroelectronics * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,11 +19,14 @@ #include <linux/module.h> #include <linux/spi/spi.h> #include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/of_irq.h> #include <linux/of_gpio.h> +#include <linux/acpi.h> #include <linux/tpm.h> #include <linux/platform_data/st33zp24.h> +#include "../tpm.h" #include "st33zp24.h" #define TPM_DATA_FIFO 0x24 @@ -66,7 +69,7 @@ struct st33zp24_spi_phy { struct spi_device *spi_device; - struct spi_transfer spi_xfer; + u8 tx_buf[ST33ZP24_SPI_BUFFER_SIZE]; u8 rx_buf[ST33ZP24_SPI_BUFFER_SIZE]; @@ -110,43 +113,39 @@ static int st33zp24_status_to_errno(u8 code) static int st33zp24_spi_send(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size) { - u8 data = 0; - int total_length = 0, nbr_dummy_bytes = 0, ret = 0; + int total_length = 0, ret = 0; struct st33zp24_spi_phy *phy = phy_id; struct spi_device *dev = phy->spi_device; - u8 *tx_buf = (u8 *)phy->spi_xfer.tx_buf; - u8 *rx_buf = phy->spi_xfer.rx_buf; + struct spi_transfer spi_xfer = { + .tx_buf = phy->tx_buf, + .rx_buf = phy->rx_buf, + }; /* Pre-Header */ - data = TPM_WRITE_DIRECTION | LOCALITY0; - memcpy(tx_buf + total_length, &data, sizeof(data)); - total_length++; - data = tpm_register; - memcpy(tx_buf + total_length, &data, sizeof(data)); - total_length++; + phy->tx_buf[total_length++] = TPM_WRITE_DIRECTION | LOCALITY0; + phy->tx_buf[total_length++] = tpm_register; if (tpm_size > 0 && tpm_register == TPM_DATA_FIFO) { - tx_buf[total_length++] = tpm_size >> 8; - tx_buf[total_length++] = tpm_size; + phy->tx_buf[total_length++] = tpm_size >> 8; + phy->tx_buf[total_length++] = tpm_size; } - memcpy(&tx_buf[total_length], tpm_data, tpm_size); + memcpy(&phy->tx_buf[total_length], tpm_data, tpm_size); total_length += tpm_size; - nbr_dummy_bytes = phy->latency; - memset(&tx_buf[total_length], TPM_DUMMY_BYTE, nbr_dummy_bytes); + memset(&phy->tx_buf[total_length], TPM_DUMMY_BYTE, phy->latency); - phy->spi_xfer.len = total_length + nbr_dummy_bytes; + spi_xfer.len = total_length + phy->latency; - ret = spi_sync_transfer(dev, &phy->spi_xfer, 1); + ret = spi_sync_transfer(dev, &spi_xfer, 1); if (ret == 0) - ret = rx_buf[total_length + nbr_dummy_bytes - 1]; + ret = phy->rx_buf[total_length + phy->latency - 1]; return st33zp24_status_to_errno(ret); } /* st33zp24_spi_send() */ /* - * read8_recv + * st33zp24_spi_read8_recv * Recv byte from the TIS register according to the ST33ZP24 SPI protocol. * @param: phy_id, the phy description * @param: tpm_register, the tpm tis register where the data should be read @@ -154,40 +153,37 @@ static int st33zp24_spi_send(void *phy_id, u8 tpm_register, u8 *tpm_data, * @param: tpm_size, tpm TPM response size to read. * @return: should be zero if success else a negative error code. */ -static int read8_reg(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size) +static int st33zp24_spi_read8_reg(void *phy_id, u8 tpm_register, u8 *tpm_data, + int tpm_size) { - u8 data = 0; - int total_length = 0, nbr_dummy_bytes, ret; + int total_length = 0, ret; struct st33zp24_spi_phy *phy = phy_id; struct spi_device *dev = phy->spi_device; - u8 *tx_buf = (u8 *)phy->spi_xfer.tx_buf; - u8 *rx_buf = phy->spi_xfer.rx_buf; + struct spi_transfer spi_xfer = { + .tx_buf = phy->tx_buf, + .rx_buf = phy->rx_buf, + }; /* Pre-Header */ - data = LOCALITY0; - memcpy(tx_buf + total_length, &data, sizeof(data)); - total_length++; - data = tpm_register; - memcpy(tx_buf + total_length, &data, sizeof(data)); - total_length++; + phy->tx_buf[total_length++] = LOCALITY0; + phy->tx_buf[total_length++] = tpm_register; - nbr_dummy_bytes = phy->latency; - memset(&tx_buf[total_length], TPM_DUMMY_BYTE, - nbr_dummy_bytes + tpm_size); + memset(&phy->tx_buf[total_length], TPM_DUMMY_BYTE, + phy->latency + tpm_size); - phy->spi_xfer.len = total_length + nbr_dummy_bytes + tpm_size; + spi_xfer.len = total_length + phy->latency + tpm_size; /* header + status byte + size of the data + status byte */ - ret = spi_sync_transfer(dev, &phy->spi_xfer, 1); + ret = spi_sync_transfer(dev, &spi_xfer, 1); if (tpm_size > 0 && ret == 0) { - ret = rx_buf[total_length + nbr_dummy_bytes - 1]; + ret = phy->rx_buf[total_length + phy->latency - 1]; - memcpy(tpm_data, rx_buf + total_length + nbr_dummy_bytes, + memcpy(tpm_data, phy->rx_buf + total_length + phy->latency, tpm_size); } return ret; -} /* read8_reg() */ +} /* st33zp24_spi_read8_reg() */ /* * st33zp24_spi_recv @@ -203,13 +199,13 @@ static int st33zp24_spi_recv(void *phy_id, u8 tpm_register, u8 *tpm_data, { int ret; - ret = read8_reg(phy_id, tpm_register, tpm_data, tpm_size); + ret = st33zp24_spi_read8_reg(phy_id, tpm_register, tpm_data, tpm_size); if (!st33zp24_status_to_errno(ret)) return tpm_size; return ret; } /* st33zp24_spi_recv() */ -static int evaluate_latency(void *phy_id) +static int st33zp24_spi_evaluate_latency(void *phy_id) { struct st33zp24_spi_phy *phy = phy_id; int latency = 1, status = 0; @@ -217,9 +213,15 @@ static int evaluate_latency(void *phy_id) while (!status && latency < MAX_SPI_LATENCY) { phy->latency = latency; - status = read8_reg(phy_id, TPM_INTF_CAPABILITY, &data, 1); + status = st33zp24_spi_read8_reg(phy_id, TPM_INTF_CAPABILITY, + &data, 1); latency++; } + if (status < 0) + return status; + if (latency == MAX_SPI_LATENCY) + return -ENODEV; + return latency - 1; } /* evaluate_latency() */ @@ -228,24 +230,52 @@ static const struct st33zp24_phy_ops spi_phy_ops = { .recv = st33zp24_spi_recv, }; -#ifdef CONFIG_OF -static int tpm_stm_spi_of_request_resources(struct st33zp24_spi_phy *phy) +static int st33zp24_spi_acpi_request_resources(struct spi_device *spi_dev) { + struct tpm_chip *chip = spi_get_drvdata(spi_dev); + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); + struct st33zp24_spi_phy *phy = tpm_dev->phy_id; + struct gpio_desc *gpiod_lpcpd; + struct device *dev = &spi_dev->dev; + + /* Get LPCPD GPIO from ACPI */ + gpiod_lpcpd = devm_gpiod_get_index(dev, "TPM IO LPCPD", 1, + GPIOD_OUT_HIGH); + if (IS_ERR(gpiod_lpcpd)) { + dev_err(dev, "Failed to retrieve lpcpd-gpios from acpi.\n"); + phy->io_lpcpd = -1; + /* + * lpcpd pin is not specified. This is not an issue as + * power management can be also managed by TPM specific + * commands. So leave with a success status code. + */ + return 0; + } + + phy->io_lpcpd = desc_to_gpio(gpiod_lpcpd); + + return 0; +} + +static int st33zp24_spi_of_request_resources(struct spi_device *spi_dev) +{ + struct tpm_chip *chip = spi_get_drvdata(spi_dev); + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); + struct st33zp24_spi_phy *phy = tpm_dev->phy_id; struct device_node *pp; - struct spi_device *dev = phy->spi_device; int gpio; int ret; - pp = dev->dev.of_node; + pp = spi_dev->dev.of_node; if (!pp) { - dev_err(&dev->dev, "No platform data\n"); + dev_err(&spi_dev->dev, "No platform data\n"); return -ENODEV; } /* Get GPIO from device tree */ gpio = of_get_named_gpio(pp, "lpcpd-gpios", 0); if (gpio < 0) { - dev_err(&dev->dev, + dev_err(&spi_dev->dev, "Failed to retrieve lpcpd-gpios from dts.\n"); phy->io_lpcpd = -1; /* @@ -256,26 +286,22 @@ static int tpm_stm_spi_of_request_resources(struct st33zp24_spi_phy *phy) return 0; } /* GPIO request and configuration */ - ret = devm_gpio_request_one(&dev->dev, gpio, + ret = devm_gpio_request_one(&spi_dev->dev, gpio, GPIOF_OUT_INIT_HIGH, "TPM IO LPCPD"); if (ret) { - dev_err(&dev->dev, "Failed to request lpcpd pin\n"); + dev_err(&spi_dev->dev, "Failed to request lpcpd pin\n"); return -ENODEV; } phy->io_lpcpd = gpio; return 0; } -#else -static int tpm_stm_spi_of_request_resources(struct st33zp24_spi_phy *phy) -{ - return -ENODEV; -} -#endif -static int tpm_stm_spi_request_resources(struct spi_device *dev, - struct st33zp24_spi_phy *phy) +static int st33zp24_spi_request_resources(struct spi_device *dev) { + struct tpm_chip *chip = spi_get_drvdata(dev); + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); + struct st33zp24_spi_phy *phy = tpm_dev->phy_id; struct st33zp24_platform_data *pdata; int ret; @@ -303,13 +329,12 @@ static int tpm_stm_spi_request_resources(struct spi_device *dev, } /* - * tpm_st33_spi_probe initialize the TPM device + * st33zp24_spi_probe initialize the TPM device * @param: dev, the spi_device drescription (TPM SPI description). * @return: 0 in case of success. * or a negative value describing the error. */ -static int -tpm_st33_spi_probe(struct spi_device *dev) +static int st33zp24_spi_probe(struct spi_device *dev) { int ret; struct st33zp24_platform_data *pdata; @@ -328,21 +353,23 @@ tpm_st33_spi_probe(struct spi_device *dev) return -ENOMEM; phy->spi_device = dev; + pdata = dev->dev.platform_data; if (!pdata && dev->dev.of_node) { - ret = tpm_stm_spi_of_request_resources(phy); + ret = st33zp24_spi_of_request_resources(dev); if (ret) return ret; } else if (pdata) { - ret = tpm_stm_spi_request_resources(dev, phy); + ret = st33zp24_spi_request_resources(dev); + if (ret) + return ret; + } else if (ACPI_HANDLE(&dev->dev)) { + ret = st33zp24_spi_acpi_request_resources(dev); if (ret) return ret; } - phy->spi_xfer.tx_buf = phy->tx_buf; - phy->spi_xfer.rx_buf = phy->rx_buf; - - phy->latency = evaluate_latency(phy); + phy->latency = st33zp24_spi_evaluate_latency(phy); if (phy->latency <= 0) return -ENODEV; @@ -351,11 +378,11 @@ tpm_st33_spi_probe(struct spi_device *dev) } /* - * tpm_st33_spi_remove remove the TPM device + * st33zp24_spi_remove remove the TPM device * @param: client, the spi_device drescription (TPM SPI description). * @return: 0 in case of success. */ -static int tpm_st33_spi_remove(struct spi_device *dev) +static int st33zp24_spi_remove(struct spi_device *dev) { struct tpm_chip *chip = spi_get_drvdata(dev); @@ -368,29 +395,34 @@ static const struct spi_device_id st33zp24_spi_id[] = { }; MODULE_DEVICE_TABLE(spi, st33zp24_spi_id); -#ifdef CONFIG_OF static const struct of_device_id of_st33zp24_spi_match[] = { { .compatible = "st,st33zp24-spi", }, {} }; MODULE_DEVICE_TABLE(of, of_st33zp24_spi_match); -#endif + +static const struct acpi_device_id st33zp24_spi_acpi_match[] = { + {"SMO3324"}, + {} +}; +MODULE_DEVICE_TABLE(acpi, st33zp24_spi_acpi_match); static SIMPLE_DEV_PM_OPS(st33zp24_spi_ops, st33zp24_pm_suspend, st33zp24_pm_resume); -static struct spi_driver tpm_st33_spi_driver = { +static struct spi_driver st33zp24_spi_driver = { .driver = { .name = TPM_ST33_SPI, .pm = &st33zp24_spi_ops, .of_match_table = of_match_ptr(of_st33zp24_spi_match), + .acpi_match_table = ACPI_PTR(st33zp24_spi_acpi_match), }, - .probe = tpm_st33_spi_probe, - .remove = tpm_st33_spi_remove, + .probe = st33zp24_spi_probe, + .remove = st33zp24_spi_remove, .id_table = st33zp24_spi_id, }; -module_spi_driver(tpm_st33_spi_driver); +module_spi_driver(st33zp24_spi_driver); MODULE_AUTHOR("TPM support (TPMsupport@list.st.com)"); MODULE_DESCRIPTION("STM TPM 1.2 SPI ST33 Driver"); diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c index 8d626784c..c2ee30451 100644 --- a/drivers/char/tpm/st33zp24/st33zp24.c +++ b/drivers/char/tpm/st33zp24/st33zp24.c @@ -1,6 +1,6 @@ /* * STMicroelectronics TPM Linux driver for TPM ST33ZP24 - * Copyright (C) 2009 - 2015 STMicroelectronics + * Copyright (C) 2009 - 2016 STMicroelectronics * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -73,14 +73,6 @@ enum tis_defaults { TIS_LONG_TIMEOUT = 2000, }; -struct st33zp24_dev { - struct tpm_chip *chip; - void *phy_id; - const struct st33zp24_phy_ops *ops; - u32 intrs; - int io_lpcpd; -}; - /* * clear_interruption clear the pending interrupt. * @param: tpm_dev, the tpm device device. @@ -102,11 +94,9 @@ static u8 clear_interruption(struct st33zp24_dev *tpm_dev) */ static void st33zp24_cancel(struct tpm_chip *chip) { - struct st33zp24_dev *tpm_dev; + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); u8 data; - tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip); - data = TPM_STS_COMMAND_READY; tpm_dev->ops->send(tpm_dev->phy_id, TPM_STS, &data, 1); } /* st33zp24_cancel() */ @@ -118,11 +108,9 @@ static void st33zp24_cancel(struct tpm_chip *chip) */ static u8 st33zp24_status(struct tpm_chip *chip) { - struct st33zp24_dev *tpm_dev; + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); u8 data; - tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip); - tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS, &data, 1); return data; } /* st33zp24_status() */ @@ -134,17 +122,15 @@ static u8 st33zp24_status(struct tpm_chip *chip) */ static int check_locality(struct tpm_chip *chip) { - struct st33zp24_dev *tpm_dev; + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); u8 data; u8 status; - tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip); - status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_ACCESS, &data, 1); if (status && (data & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) - return chip->vendor.locality; + return tpm_dev->locality; return -EACCES; } /* check_locality() */ @@ -156,27 +142,25 @@ static int check_locality(struct tpm_chip *chip) */ static int request_locality(struct tpm_chip *chip) { + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); unsigned long stop; long ret; - struct st33zp24_dev *tpm_dev; u8 data; - if (check_locality(chip) == chip->vendor.locality) - return chip->vendor.locality; - - tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip); + if (check_locality(chip) == tpm_dev->locality) + return tpm_dev->locality; data = TPM_ACCESS_REQUEST_USE; ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1); if (ret < 0) return ret; - stop = jiffies + chip->vendor.timeout_a; + stop = jiffies + chip->timeout_a; /* Request locality is usually effective after the request */ do { if (check_locality(chip) >= 0) - return chip->vendor.locality; + return tpm_dev->locality; msleep(TPM_TIMEOUT); } while (time_before(jiffies, stop)); @@ -190,10 +174,9 @@ static int request_locality(struct tpm_chip *chip) */ static void release_locality(struct tpm_chip *chip) { - struct st33zp24_dev *tpm_dev; + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); u8 data; - tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip); data = TPM_ACCESS_ACTIVE_LOCALITY; tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1); @@ -206,23 +189,21 @@ static void release_locality(struct tpm_chip *chip) */ static int get_burstcount(struct tpm_chip *chip) { + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); unsigned long stop; int burstcnt, status; - u8 tpm_reg, temp; - struct st33zp24_dev *tpm_dev; - - tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip); + u8 temp; - stop = jiffies + chip->vendor.timeout_d; + stop = jiffies + chip->timeout_d; do { - tpm_reg = TPM_STS + 1; - status = tpm_dev->ops->recv(tpm_dev->phy_id, tpm_reg, &temp, 1); + status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS + 1, + &temp, 1); if (status < 0) return -EBUSY; - tpm_reg = TPM_STS + 2; burstcnt = temp; - status = tpm_dev->ops->recv(tpm_dev->phy_id, tpm_reg, &temp, 1); + status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS + 2, + &temp, 1); if (status < 0) return -EBUSY; @@ -271,15 +252,13 @@ static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, wait_queue_head_t *queue, bool check_cancel) { + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); unsigned long stop; int ret = 0; bool canceled = false; bool condition; u32 cur_intrs; u8 status; - struct st33zp24_dev *tpm_dev; - - tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip); /* check current status */ status = st33zp24_status(chip); @@ -288,10 +267,10 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, stop = jiffies + timeout; - if (chip->vendor.irq) { + if (chip->flags & TPM_CHIP_FLAG_IRQ) { cur_intrs = tpm_dev->intrs; clear_interruption(tpm_dev); - enable_irq(chip->vendor.irq); + enable_irq(tpm_dev->irq); do { if (ret == -ERESTARTSYS && freezing(current)) @@ -314,7 +293,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, } } while (ret == -ERESTARTSYS && freezing(current)); - disable_irq_nosync(chip->vendor.irq); + disable_irq_nosync(tpm_dev->irq); } else { do { @@ -337,16 +316,14 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, */ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) { + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); int size = 0, burstcnt, len, ret; - struct st33zp24_dev *tpm_dev; - - tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip); while (size < count && wait_for_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, - chip->vendor.timeout_c, - &chip->vendor.read_queue, true) == 0) { + chip->timeout_c, + &tpm_dev->read_queue, true) == 0) { burstcnt = get_burstcount(chip); if (burstcnt < 0) return burstcnt; @@ -370,13 +347,11 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id) { struct tpm_chip *chip = dev_id; - struct st33zp24_dev *tpm_dev; - - tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip); + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); tpm_dev->intrs++; - wake_up_interruptible(&chip->vendor.read_queue); - disable_irq_nosync(chip->vendor.irq); + wake_up_interruptible(&tpm_dev->read_queue); + disable_irq_nosync(tpm_dev->irq); return IRQ_HANDLED; } /* tpm_ioserirq_handler() */ @@ -393,19 +368,17 @@ static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id) static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf, size_t len) { + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); u32 status, i, size, ordinal; int burstcnt = 0; int ret; u8 data; - struct st33zp24_dev *tpm_dev; if (!chip) return -EBUSY; if (len < TPM_HEADER_SIZE) return -EBUSY; - tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip); - ret = request_locality(chip); if (ret < 0) return ret; @@ -414,8 +387,8 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf, if ((status & TPM_STS_COMMAND_READY) == 0) { st33zp24_cancel(chip); if (wait_for_stat - (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, - &chip->vendor.read_queue, false) < 0) { + (chip, TPM_STS_COMMAND_READY, chip->timeout_b, + &tpm_dev->read_queue, false) < 0) { ret = -ETIME; goto out_err; } @@ -456,12 +429,12 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf, if (ret < 0) goto out_err; - if (chip->vendor.irq) { + if (chip->flags & TPM_CHIP_FLAG_IRQ) { ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); ret = wait_for_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, tpm_calc_ordinal_duration(chip, ordinal), - &chip->vendor.read_queue, false); + &tpm_dev->read_queue, false); if (ret < 0) goto out_err; } @@ -532,6 +505,7 @@ static bool st33zp24_req_canceled(struct tpm_chip *chip, u8 status) } static const struct tpm_class_ops st33zp24_tpm = { + .flags = TPM_OPS_AUTO_STARTUP, .send = st33zp24_send, .recv = st33zp24_recv, .cancel = st33zp24_cancel, @@ -565,20 +539,20 @@ int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops, if (!tpm_dev) return -ENOMEM; - TPM_VPRIV(chip) = tpm_dev; tpm_dev->phy_id = phy_id; tpm_dev->ops = ops; + dev_set_drvdata(&chip->dev, tpm_dev); - chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); - chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); - chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); - chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + chip->timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + chip->timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); + chip->timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); + chip->timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); - chip->vendor.locality = LOCALITY0; + tpm_dev->locality = LOCALITY0; if (irq) { /* INTERRUPT Setup */ - init_waitqueue_head(&chip->vendor.read_queue); + init_waitqueue_head(&tpm_dev->read_queue); tpm_dev->intrs = 0; if (request_locality(chip) != LOCALITY0) { @@ -611,16 +585,14 @@ int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops, if (ret < 0) goto _tpm_clean_answer; - chip->vendor.irq = irq; + tpm_dev->irq = irq; + chip->flags |= TPM_CHIP_FLAG_IRQ; - disable_irq_nosync(chip->vendor.irq); + disable_irq_nosync(tpm_dev->irq); tpm_gen_interrupt(chip); } - tpm_get_timeouts(chip); - tpm_do_selftest(chip); - return tpm_chip_register(chip); _tpm_clean_answer: dev_info(&chip->dev, "TPM initialization fail\n"); @@ -650,10 +622,9 @@ EXPORT_SYMBOL(st33zp24_remove); int st33zp24_pm_suspend(struct device *dev) { struct tpm_chip *chip = dev_get_drvdata(dev); - struct st33zp24_dev *tpm_dev; - int ret = 0; + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); - tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip); + int ret = 0; if (gpio_is_valid(tpm_dev->io_lpcpd)) gpio_set_value(tpm_dev->io_lpcpd, 0); @@ -672,16 +643,14 @@ EXPORT_SYMBOL(st33zp24_pm_suspend); int st33zp24_pm_resume(struct device *dev) { struct tpm_chip *chip = dev_get_drvdata(dev); - struct st33zp24_dev *tpm_dev; + struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); int ret = 0; - tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip); - if (gpio_is_valid(tpm_dev->io_lpcpd)) { gpio_set_value(tpm_dev->io_lpcpd, 1); ret = wait_for_stat(chip, - TPM_STS_VALID, chip->vendor.timeout_b, - &chip->vendor.read_queue, false); + TPM_STS_VALID, chip->timeout_b, + &tpm_dev->read_queue, false); } else { ret = tpm_pm_resume(dev); if (!ret) diff --git a/drivers/char/tpm/st33zp24/st33zp24.h b/drivers/char/tpm/st33zp24/st33zp24.h index c207cebf6..6f4a4198a 100644 --- a/drivers/char/tpm/st33zp24/st33zp24.h +++ b/drivers/char/tpm/st33zp24/st33zp24.h @@ -1,6 +1,6 @@ /* * STMicroelectronics TPM Linux driver for TPM ST33ZP24 - * Copyright (C) 2009 - 2015 STMicroelectronics + * Copyright (C) 2009 - 2016 STMicroelectronics * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -21,6 +21,18 @@ #define TPM_WRITE_DIRECTION 0x80 #define TPM_BUFSIZE 2048 +struct st33zp24_dev { + struct tpm_chip *chip; + void *phy_id; + const struct st33zp24_phy_ops *ops; + int locality; + int irq; + u32 intrs; + int io_lpcpd; + wait_queue_head_t read_queue; +}; + + struct st33zp24_phy_ops { int (*send)(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size); int (*recv)(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size); |