summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-29 17:38:46 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-29 17:38:46 -0700
commit7a1e8b80fb1e8ead4cec15d1fc494ed290e4d2e9 (patch)
tree55a36d4256f1ae793b5c8e88c0f158737447193f /drivers
parenta867d7349e94b6409b08629886a819f802377e91 (diff)
parent7616ac70d1bb4f2e9d25c1a82d283f3368a7b632 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris: "Highlights: - TPM core and driver updates/fixes - IPv6 security labeling (CALIPSO) - Lots of Apparmor fixes - Seccomp: remove 2-phase API, close hole where ptrace can change syscall #" * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (156 commits) apparmor: fix SECURITY_APPARMOR_HASH_DEFAULT parameter handling tpm: Add TPM 2.0 support to the Nuvoton i2c driver (NPCT6xx family) tpm: Factor out common startup code tpm: use devm_add_action_or_reset tpm2_i2c_nuvoton: add irq validity check tpm: read burstcount from TPM_STS in one 32-bit transaction tpm: fix byte-order for the value read by tpm2_get_tpm_pt tpm_tis_core: convert max timeouts from msec to jiffies apparmor: fix arg_size computation for when setprocattr is null terminated apparmor: fix oops, validate buffer size in apparmor_setprocattr() apparmor: do not expose kernel stack apparmor: fix module parameters can be changed after policy is locked apparmor: fix oops in profile_unpack() when policy_db is not present apparmor: don't check for vmalloc_addr if kvzalloc() failed apparmor: add missing id bounds check on dfa verification apparmor: allow SYS_CAP_RESOURCE to be sufficient to prlimit another task apparmor: use list_next_entry instead of list_entry_next apparmor: fix refcount race when finding a child profile apparmor: fix ref count leak when profile sha1 hash is read apparmor: check that xindex is in trans_table bounds ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/tpm/Kconfig30
-rw-r--r--drivers/char/tpm/Makefile3
-rw-r--r--drivers/char/tpm/st33zp24/Kconfig11
-rw-r--r--drivers/char/tpm/st33zp24/i2c.c70
-rw-r--r--drivers/char/tpm/st33zp24/spi.c184
-rw-r--r--drivers/char/tpm/st33zp24/st33zp24.c129
-rw-r--r--drivers/char/tpm/st33zp24/st33zp24.h14
-rw-r--r--drivers/char/tpm/tpm-chip.c299
-rw-r--r--drivers/char/tpm/tpm-dev.c15
-rw-r--r--drivers/char/tpm/tpm-interface.c132
-rw-r--r--drivers/char/tpm/tpm-sysfs.c78
-rw-r--r--drivers/char/tpm/tpm.h82
-rw-r--r--drivers/char/tpm/tpm2-cmd.c59
-rw-r--r--drivers/char/tpm/tpm_atmel.c63
-rw-r--r--drivers/char/tpm/tpm_atmel.h16
-rw-r--r--drivers/char/tpm/tpm_crb.c85
-rw-r--r--drivers/char/tpm/tpm_eventlog.c2
-rw-r--r--drivers/char/tpm/tpm_eventlog.h4
-rw-r--r--drivers/char/tpm/tpm_i2c_atmel.c45
-rw-r--r--drivers/char/tpm/tpm_i2c_infineon.c59
-rw-r--r--drivers/char/tpm/tpm_i2c_nuvoton.c131
-rw-r--r--drivers/char/tpm/tpm_ibmvtpm.c38
-rw-r--r--drivers/char/tpm/tpm_infineon.c22
-rw-r--r--drivers/char/tpm/tpm_nsc.c84
-rw-r--r--drivers/char/tpm/tpm_tis.c829
-rw-r--r--drivers/char/tpm/tpm_tis_core.c835
-rw-r--r--drivers/char/tpm/tpm_tis_core.h156
-rw-r--r--drivers/char/tpm/tpm_tis_spi.c272
-rw-r--r--drivers/char/tpm/tpm_vtpm_proxy.c637
-rw-r--r--drivers/char/tpm/xen-tpmfront.c36
30 files changed, 2968 insertions, 1452 deletions
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 3b84a8b1bfbe..9faa0b1e7766 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -24,9 +24,16 @@ menuconfig TCG_TPM
if TCG_TPM
+config TCG_TIS_CORE
+ tristate
+ ---help---
+ TCG TIS TPM core driver. It implements the TPM TCG TIS logic and hooks
+ into the TPM kernel APIs. Physical layers will register against it.
+
config TCG_TIS
tristate "TPM Interface Specification 1.2 Interface / TPM 2.0 FIFO Interface"
depends on X86
+ select TCG_TIS_CORE
---help---
If you have a TPM security chip that is compliant with the
TCG TIS 1.2 TPM specification (TPM1.2) or the TCG PTP FIFO
@@ -34,6 +41,18 @@ config TCG_TIS
within Linux. To compile this driver as a module, choose M here;
the module will be called tpm_tis.
+config TCG_TIS_SPI
+ tristate "TPM Interface Specification 1.3 Interface / TPM 2.0 FIFO Interface - (SPI)"
+ depends on SPI
+ select TCG_TIS_CORE
+ ---help---
+ If you have a TPM security chip which is connected to a regular,
+ non-tcg SPI master (i.e. most embedded platforms) that is compliant with the
+ TCG TIS 1.3 TPM specification (TPM1.2) or the TCG PTP FIFO
+ specification (TPM2.0) say Yes and it will be accessible from
+ within Linux. To compile this driver as a module, choose M here;
+ the module will be called tpm_tis_spi.
+
config TCG_TIS_I2C_ATMEL
tristate "TPM Interface Specification 1.2 Interface (I2C - Atmel)"
depends on I2C
@@ -122,5 +141,16 @@ config TCG_CRB
from within Linux. To compile this driver as a module, choose
M here; the module will be called tpm_crb.
+config TCG_VTPM_PROXY
+ tristate "VTPM Proxy Interface"
+ depends on TCG_TPM
+ select ANON_INODES
+ ---help---
+ This driver proxies for an emulated TPM (vTPM) running in userspace.
+ A device /dev/vtpmx is provided that creates a device pair
+ /dev/vtpmX and a server-side file descriptor on which the vTPM
+ can receive commands.
+
+
source "drivers/char/tpm/st33zp24/Kconfig"
endif # TCG_TPM
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 56e8f1f3dc7e..a385fb8c17de 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -12,7 +12,9 @@ ifdef CONFIG_TCG_IBMVTPM
tpm-y += tpm_eventlog.o tpm_of.o
endif
endif
+obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
obj-$(CONFIG_TCG_TIS) += tpm_tis.o
+obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi.o
obj-$(CONFIG_TCG_TIS_I2C_ATMEL) += tpm_i2c_atmel.o
obj-$(CONFIG_TCG_TIS_I2C_INFINEON) += tpm_i2c_infineon.o
obj-$(CONFIG_TCG_TIS_I2C_NUVOTON) += tpm_i2c_nuvoton.o
@@ -23,3 +25,4 @@ obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o
obj-$(CONFIG_TCG_TIS_ST33ZP24) += st33zp24/
obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o
obj-$(CONFIG_TCG_CRB) += tpm_crb.o
+obj-$(CONFIG_TCG_VTPM_PROXY) += tpm_vtpm_proxy.o
diff --git a/drivers/char/tpm/st33zp24/Kconfig b/drivers/char/tpm/st33zp24/Kconfig
index 19c007461d1c..e74c6f29fc85 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 309d2767c6a1..028a9cd76b63 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 f974c945c97a..9f5a0117098c 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 8d626784cd8d..c2ee30451e41 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))