All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/12] Few minnor fixes, rework of tpm_tis to support tcg spi and i2c.
@ 2016-03-20 19:34 Christophe Ricard
       [not found] ` <1458502483-16887-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  0 siblings, 1 reply; 39+ messages in thread
From: Christophe Ricard @ 2016-03-20 19:34 UTC (permalink / raw)
  To: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

Hi Jarkko,

Please find in this serie some few minnor fixes as well as some more work around the
tpm_tis driver.

This work is based on Peter Huewe's proposal in October 30th 2015:
https://patchwork.ozlabs.org/patch/538179/

I have tried to keep Peter's credits on related patches.

The idea is to have one main tpm_tis_core which would keep a common tpm_tis logic for
all physical layers(i2c, spi, legacy/lpc).
This tpm_tis_core can be reused by other drivers (such as st33zp24...) and would
potentially easy the maintenance.

It offers support for LPC (tpm_tis), SPI (tpm_tis_spi) and I2C (tpm_tis_i2c) following
ongoing or available TCG specifications

SPI layer is supporting wait state/Flow Control as describe in the TCG PTP specification
(chapter 6.4.5 Flow Control).

I2C layer is following TCG on going and almost finalized specification.

Physical layer i2c and spi are tested using STMicro TPM's against Minnowboard, RaspberryPi
and Beagleboard xM in both polling and interrupt mode.

For now, i haven't been able to test the LPC/legacy layer but assume it should work.

Any comment welcome :).

Best Regards
Christophe

Christophe Ricard (12):
  tpm/st33zp24/i2c: Drop two useless checks in ACPI probe path
  tpm/st33zp24/spi: Drop two useless checks in ACPI probe path
  tpm: Add include guards in tpm.h
  tpm/st33zp24: Remove unneeded tpm_reg in get_burstcount
  tpm: Add tpm_set_vendordata and tpm_get_vendordata
  devicetree: Add infineon to vendor-prefix.txt
  devicetree: Add Trusted Computing Group to vendor-prefix.txt
  tpm/tpm_tis: Split tpm_tis driver into a core and TCG TIS compliant
    phy
  tpm/tpm_tis: Rework interrupt management for phy compatibility
  tpm/tpm_tis_spi: Add support for spi phy
  tpm: Add check_data handle to tpm_class_ops in order to check data
    integrity
  tpm/tpm_tis_i2c: Add support for i2c phy

 .../bindings/security/tpm/tpm_tis_i2c.txt          |  30 +
 .../bindings/security/tpm/tpm_tis_spi.txt          |  28 +
 .../devicetree/bindings/vendor-prefixes.txt        |   2 +
 drivers/char/tpm/Kconfig                           |  24 +-
 drivers/char/tpm/Makefile                          |   4 +-
 drivers/char/tpm/st33zp24/i2c.c                    |  13 +-
 drivers/char/tpm/st33zp24/spi.c                    |  13 +-
 drivers/char/tpm/st33zp24/st33zp24.c               |  36 +-
 drivers/char/tpm/tpm-interface.c                   |  11 +-
 drivers/char/tpm/tpm.h                             |  20 +-
 drivers/char/tpm/tpm_ibmvtpm.c                     |   8 +-
 drivers/char/tpm/tpm_tis.c                         | 803 ++-------------------
 drivers/char/tpm/tpm_tis_core.c                    | 763 ++++++++++++++++++++
 drivers/char/tpm/tpm_tis_core.h                    | 166 +++++
 drivers/char/tpm/tpm_tis_i2c.c                     | 499 +++++++++++++
 drivers/char/tpm/tpm_tis_spi.c                     | 279 +++++++
 drivers/char/tpm/xen-tpmfront.c                    |  14 +-
 include/linux/tpm.h                                |   5 +
 18 files changed, 1908 insertions(+), 810 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/security/tpm/tpm_tis_i2c.txt
 create mode 100644 Documentation/devicetree/bindings/security/tpm/tpm_tis_spi.txt
 create mode 100644 drivers/char/tpm/tpm_tis_core.c
 create mode 100644 drivers/char/tpm/tpm_tis_core.h
 create mode 100644 drivers/char/tpm/tpm_tis_i2c.c
 create mode 100644 drivers/char/tpm/tpm_tis_spi.c

-- 
2.5.0


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH 01/12] tpm/st33zp24/i2c: Drop two useless checks in ACPI probe path
       [not found] ` <1458502483-16887-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2016-03-20 19:34   ` Christophe Ricard
  2016-03-20 19:34   ` [PATCH 02/12] tpm/st33zp24/spi: " Christophe Ricard
                     ` (13 subsequent siblings)
  14 siblings, 0 replies; 39+ messages in thread
From: Christophe Ricard @ 2016-03-20 19:34 UTC (permalink / raw)
  To: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

When st33zp24_i2c_acpi_request_resources() gets called we
already know that the entries in ->acpi_match_table have matched ACPI ID
of the device.
In addition I2C client pointer cannot be NULL in any case (otherwise I2C
core would not call ->probe() for the driver in the first place).

Drop the two useless checks from the driver.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/char/tpm/st33zp24/i2c.c | 13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/drivers/char/tpm/st33zp24/i2c.c b/drivers/char/tpm/st33zp24/i2c.c
index f179aad..f8e8123 100644
--- a/drivers/char/tpm/st33zp24/i2c.c
+++ b/drivers/char/tpm/st33zp24/i2c.c
@@ -113,19 +113,8 @@ static const struct st33zp24_phy_ops i2c_phy_ops = {
 static int st33zp24_i2c_acpi_request_resources(struct i2c_client *client)
 {
 	struct st33zp24_i2c_phy *phy = i2c_get_clientdata(client);
-	const struct acpi_device_id *id;
 	struct gpio_desc *gpiod_lpcpd;
-	struct device *dev;
-
-	if (!client)
-		return -EINVAL;
-
-	dev = &client->dev;
-
-	/* Match the struct device against a given list of ACPI IDs */
-	id = acpi_match_device(dev->driver->acpi_match_table, dev);
-	if (!id)
-		return -ENODEV;
+	struct device *dev = &client->dev;
 
 	/* Get LPCPD GPIO from ACPI */
 	gpiod_lpcpd = devm_gpiod_get_index(dev, "TPM IO LPCPD", 1,
-- 
2.5.0


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 02/12] tpm/st33zp24/spi: Drop two useless checks in ACPI probe path
       [not found] ` <1458502483-16887-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2016-03-20 19:34   ` [PATCH 01/12] tpm/st33zp24/i2c: Drop two useless checks in ACPI probe path Christophe Ricard
@ 2016-03-20 19:34   ` Christophe Ricard
       [not found]     ` <1458502483-16887-3-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2016-03-20 19:34   ` [PATCH 03/12] tpm: Add include guards in tpm.h Christophe Ricard
                     ` (12 subsequent siblings)
  14 siblings, 1 reply; 39+ messages in thread
From: Christophe Ricard @ 2016-03-20 19:34 UTC (permalink / raw)
  To: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

When st33zp24_spi_acpi_request_resources() gets called we
already know that the entries in ->acpi_match_table have matched ACPI ID
of the device.
In addition spi_device pointer cannot be NULL in any case (otherwise I2C
core would not call ->probe() for the driver in the first place).

Drop the two useless checks from the driver.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/char/tpm/st33zp24/spi.c | 13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/drivers/char/tpm/st33zp24/spi.c b/drivers/char/tpm/st33zp24/spi.c
index 6be51ac..608dbc6 100644
--- a/drivers/char/tpm/st33zp24/spi.c
+++ b/drivers/char/tpm/st33zp24/spi.c
@@ -232,19 +232,8 @@ static const struct st33zp24_phy_ops spi_phy_ops = {
 static int st33zp24_spi_acpi_request_resources(struct spi_device *spi_dev)
 {
 	struct st33zp24_spi_phy *phy = spi_get_drvdata(spi_dev);
-	const struct acpi_device_id *id;
 	struct gpio_desc *gpiod_lpcpd;
-	struct device *dev;
-
-	if (!spi_dev)
-		return -EINVAL;
-
-	dev = &spi_dev->dev;
-
-	/* Match the struct device against a given list of ACPI IDs */
-	id = acpi_match_device(dev->driver->acpi_match_table, dev);
-	if (!id)
-		return -ENODEV;
+	struct device *dev = &spi_dev->dev;
 
 	/* Get LPCPD GPIO from ACPI */
 	gpiod_lpcpd = devm_gpiod_get_index(dev, "TPM IO LPCPD", 1,
-- 
2.5.0


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 03/12] tpm: Add include guards in tpm.h
       [not found] ` <1458502483-16887-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2016-03-20 19:34   ` [PATCH 01/12] tpm/st33zp24/i2c: Drop two useless checks in ACPI probe path Christophe Ricard
  2016-03-20 19:34   ` [PATCH 02/12] tpm/st33zp24/spi: " Christophe Ricard
@ 2016-03-20 19:34   ` Christophe Ricard
       [not found]     ` <1458502483-16887-4-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2016-03-20 19:34   ` [PATCH 04/12] tpm/st33zp24: Remove unneeded tpm_reg in get_burstcount Christophe Ricard
                     ` (11 subsequent siblings)
  14 siblings, 1 reply; 39+ messages in thread
From: Christophe Ricard @ 2016-03-20 19:34 UTC (permalink / raw)
  To: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, Peter Huewe,
	benoit.houyere-qxv4g6HH51o

Add missing include guards in tpm.h

Signed-off-by: Peter Huewe <peter.huewe-d0qZbvYSIPpWk0Htik3J/w@public.gmane.org>
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/char/tpm/tpm.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 928b47f..28a0c17 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -19,6 +19,10 @@
  * License.
  *
  */
+
+#ifndef __TPM_H__
+#define __TPM_H__
+
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
@@ -548,3 +552,4 @@ extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32);
 extern int tpm2_do_selftest(struct tpm_chip *chip);
 extern int tpm2_gen_interrupt(struct tpm_chip *chip);
 extern int tpm2_probe(struct tpm_chip *chip);
+#endif
-- 
2.5.0


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 04/12] tpm/st33zp24: Remove unneeded tpm_reg in get_burstcount
       [not found] ` <1458502483-16887-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (2 preceding siblings ...)
  2016-03-20 19:34   ` [PATCH 03/12] tpm: Add include guards in tpm.h Christophe Ricard
@ 2016-03-20 19:34   ` Christophe Ricard
       [not found]     ` <1458502483-16887-5-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2016-03-20 19:34   ` [PATCH 05/12] tpm: Add tpm_set_vendordata and tpm_get_vendordata Christophe Ricard
                     ` (10 subsequent siblings)
  14 siblings, 1 reply; 39+ messages in thread
From: Christophe Ricard @ 2016-03-20 19:34 UTC (permalink / raw)
  To: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

We can get rid of tpm_reg variable in get_burstcount.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/char/tpm/st33zp24/st33zp24.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c
index 944d279..9e91ca7 100644
--- a/drivers/char/tpm/st33zp24/st33zp24.c
+++ b/drivers/char/tpm/st33zp24/st33zp24.c
@@ -208,21 +208,21 @@ static int get_burstcount(struct tpm_chip *chip)
 {
 	unsigned long stop;
 	int burstcnt, status;
-	u8 tpm_reg, temp;
+	u8 temp;
 	struct st33zp24_dev *tpm_dev;
 
 	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
 
 	stop = jiffies + chip->vendor.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;
 
-- 
2.5.0


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 05/12] tpm: Add tpm_set_vendordata and tpm_get_vendordata
       [not found] ` <1458502483-16887-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (3 preceding siblings ...)
  2016-03-20 19:34   ` [PATCH 04/12] tpm/st33zp24: Remove unneeded tpm_reg in get_burstcount Christophe Ricard
@ 2016-03-20 19:34   ` Christophe Ricard
       [not found]     ` <1458502483-16887-6-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2016-03-20 19:34   ` [PATCH 06/12] devicetree: Add infineon to vendor-prefix.txt Christophe Ricard
                     ` (9 subsequent siblings)
  14 siblings, 1 reply; 39+ messages in thread
From: Christophe Ricard @ 2016-03-20 19:34 UTC (permalink / raw)
  To: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

Remove TPM_VPRIV macro and replace with tpm_set_vendordata and
tpm_get_vendordata.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/char/tpm/st33zp24/st33zp24.c | 26 +++++++++++++-------------
 drivers/char/tpm/tpm.h               | 12 ++++++++++--
 drivers/char/tpm/tpm_ibmvtpm.c       |  8 ++++----
 drivers/char/tpm/tpm_tis.c           |  2 +-
 drivers/char/tpm/xen-tpmfront.c      | 14 +++++++-------
 5 files changed, 35 insertions(+), 27 deletions(-)

diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c
index 9e91ca7..dc2d0f3 100644
--- a/drivers/char/tpm/st33zp24/st33zp24.c
+++ b/drivers/char/tpm/st33zp24/st33zp24.c
@@ -105,7 +105,7 @@ static void st33zp24_cancel(struct tpm_chip *chip)
 	struct st33zp24_dev *tpm_dev;
 	u8 data;
 
-	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
+	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
 
 	data = TPM_STS_COMMAND_READY;
 	tpm_dev->ops->send(tpm_dev->phy_id, TPM_STS, &data, 1);
@@ -121,7 +121,7 @@ static u8 st33zp24_status(struct tpm_chip *chip)
 	struct st33zp24_dev *tpm_dev;
 	u8 data;
 
-	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
+	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
 
 	tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS, &data, 1);
 	return data;
@@ -138,7 +138,7 @@ static int check_locality(struct tpm_chip *chip)
 	u8 data;
 	u8 status;
 
-	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
+	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
 
 	status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
 	if (status && (data &
@@ -164,7 +164,7 @@ static int request_locality(struct tpm_chip *chip)
 	if (check_locality(chip) == chip->vendor.locality)
 		return chip->vendor.locality;
 
-	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
+	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
 
 	data = TPM_ACCESS_REQUEST_USE;
 	ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
@@ -193,7 +193,7 @@ static void release_locality(struct tpm_chip *chip)
 	struct st33zp24_dev *tpm_dev;
 	u8 data;
 
-	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
+	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
 	data = TPM_ACCESS_ACTIVE_LOCALITY;
 
 	tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
@@ -211,7 +211,7 @@ static int get_burstcount(struct tpm_chip *chip)
 	u8 temp;
 	struct st33zp24_dev *tpm_dev;
 
-	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
+	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
 
 	stop = jiffies + chip->vendor.timeout_d;
 	do {
@@ -279,7 +279,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
 	u8 status;
 	struct st33zp24_dev *tpm_dev;
 
-	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
+	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
 
 	/* check current status */
 	status = st33zp24_status(chip);
@@ -340,7 +340,7 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
 	int size = 0, burstcnt, len, ret;
 	struct st33zp24_dev *tpm_dev;
 
-	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
+	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
 
 	while (size < count &&
 	       wait_for_stat(chip,
@@ -372,7 +372,7 @@ 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);
+	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
 
 	tpm_dev->intrs++;
 	wake_up_interruptible(&chip->vendor.read_queue);
@@ -404,7 +404,7 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf,
 	if (len < TPM_HEADER_SIZE)
 		return -EBUSY;
 
-	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
+	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
 
 	ret = request_locality(chip);
 	if (ret < 0)
@@ -565,7 +565,7 @@ int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops,
 	if (!tpm_dev)
 		return -ENOMEM;
 
-	TPM_VPRIV(chip) = tpm_dev;
+	tpm_set_vendordata(chip, tpm_dev);
 	tpm_dev->phy_id = phy_id;
 	tpm_dev->ops = ops;
 
@@ -653,7 +653,7 @@ int st33zp24_pm_suspend(struct device *dev)
 	struct st33zp24_dev *tpm_dev;
 	int ret = 0;
 
-	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
+	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
 
 	if (gpio_is_valid(tpm_dev->io_lpcpd))
 		gpio_set_value(tpm_dev->io_lpcpd, 0);
@@ -675,7 +675,7 @@ int st33zp24_pm_resume(struct device *dev)
 	struct st33zp24_dev *tpm_dev;
 	int ret = 0;
 
-	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
+	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
 
 	if (gpio_is_valid(tpm_dev->io_lpcpd)) {
 		gpio_set_value(tpm_dev->io_lpcpd, 1);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 28a0c17..6a973b9 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -157,8 +157,6 @@ struct tpm_vendor_specific {
 	u16 manufacturer_id;
 };
 
-#define TPM_VPRIV(c)     ((c)->vendor.priv)
-
 #define TPM_VID_INTEL    0x8086
 #define TPM_VID_WINBOND  0x1050
 #define TPM_VID_STM      0x104A
@@ -203,6 +201,16 @@ struct tpm_chip {
 
 #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
 
+static inline void tpm_set_vendordata(struct tpm_chip *chip, void *data)
+{
+	chip->vendor.priv = data;
+}
+
+static inline void *tpm_get_vendordata(struct tpm_chip *chip)
+{
+	return chip->vendor.priv;
+}
+
 static inline int tpm_read_index(int base, int index)
 {
 	outb(index, base);
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c
index b0a9a9e..c8b1643 100644
--- a/drivers/char/tpm/tpm_ibmvtpm.c
+++ b/drivers/char/tpm/tpm_ibmvtpm.c
@@ -64,7 +64,7 @@ static struct ibmvtpm_dev *ibmvtpm_get_data(const struct device *dev)
 {
 	struct tpm_chip *chip = dev_get_drvdata(dev);
 	if (chip)
-		return (struct ibmvtpm_dev *)TPM_VPRIV(chip);
+		return (struct ibmvtpm_dev *)tpm_get_vendordata(chip);
 	return NULL;
 }
 
@@ -83,7 +83,7 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 	u16 len;
 	int sig;
 
-	ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
+	ibmvtpm = (struct ibmvtpm_dev *)tpm_get_vendordata(chip);
 
 	if (!ibmvtpm->rtce_buf) {
 		dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
@@ -127,7 +127,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
 	__be64 *word = (__be64 *)&crq;
 	int rc, sig;
 
-	ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
+	ibmvtpm = (struct ibmvtpm_dev *)tpm_get_vendordata(chip);
 
 	if (!ibmvtpm->rtce_buf) {
 		dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
@@ -643,7 +643,7 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
 
 	crq_q->index = 0;
 
-	TPM_VPRIV(chip) = (void *)ibmvtpm;
+	tpm_set_vendordata(chip, (void *)ibmvtpm);
 
 	spin_lock_init(&ibmvtpm->rtce_lock);
 
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index eed3bf5..607fa3f 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -678,7 +678,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
 	if (IS_ERR(chip))
 		return PTR_ERR(chip);
 
-	chip->vendor.priv = priv;
+	tpm_set_vendordata(chip, priv);
 #ifdef CONFIG_ACPI
 	chip->acpi_dev_handle = acpi_dev_handle;
 #endif
diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c
index 3111f27..c472fd8 100644
--- a/drivers/char/tpm/xen-tpmfront.c
+++ b/drivers/char/tpm/xen-tpmfront.c
@@ -39,7 +39,7 @@ enum status_bits {
 
 static u8 vtpm_status(struct tpm_chip *chip)
 {
-	struct tpm_private *priv = TPM_VPRIV(chip);
+	struct tpm_private *priv = tpm_get_vendordata(chip);
 	switch (priv->shr->state) {
 	case VTPM_STATE_IDLE:
 		return VTPM_STATUS_IDLE | VTPM_STATUS_CANCELED;
@@ -60,7 +60,7 @@ static bool vtpm_req_canceled(struct tpm_chip *chip, u8 status)
 
 static void vtpm_cancel(struct tpm_chip *chip)
 {
-	struct tpm_private *priv = TPM_VPRIV(chip);
+	struct tpm_private *priv = tpm_get_vendordata(chip);
 	priv->shr->state = VTPM_STATE_CANCEL;
 	wmb();
 	notify_remote_via_evtchn(priv->evtchn);
@@ -73,7 +73,7 @@ static unsigned int shr_data_offset(struct vtpm_shared_page *shr)
 
 static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
 {
-	struct tpm_private *priv = TPM_VPRIV(chip);
+	struct tpm_private *priv = tpm_get_vendordata(chip);
 	struct vtpm_shared_page *shr = priv->shr;
 	unsigned int offset = shr_data_offset(shr);
 
@@ -115,7 +115,7 @@ static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
 
 static int vtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 {
-	struct tpm_private *priv = TPM_VPRIV(chip);
+	struct tpm_private *priv = tpm_get_vendordata(chip);
 	struct vtpm_shared_page *shr = priv->shr;
 	unsigned int offset = shr_data_offset(shr);
 	size_t length = shr->length;
@@ -182,7 +182,7 @@ static int setup_chip(struct device *dev, struct tpm_private *priv)
 	init_waitqueue_head(&chip->vendor.read_queue);
 
 	priv->chip = chip;
-	TPM_VPRIV(chip) = priv;
+	tpm_set_vendordata(chip, priv);
 
 	return 0;
 }
@@ -318,10 +318,10 @@ static int tpmfront_probe(struct xenbus_device *dev,
 static int tpmfront_remove(struct xenbus_device *dev)
 {
 	struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
-	struct tpm_private *priv = TPM_VPRIV(chip);
+	struct tpm_private *priv = tpm_get_vendordata(chip);
 	tpm_chip_unregister(chip);
 	ring_free(priv);
-	TPM_VPRIV(chip) = NULL;
+	tpm_set_vendordata(chip, NULL);
 	return 0;
 }
 
-- 
2.5.0


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 06/12] devicetree: Add infineon to vendor-prefix.txt
       [not found] ` <1458502483-16887-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (4 preceding siblings ...)
  2016-03-20 19:34   ` [PATCH 05/12] tpm: Add tpm_set_vendordata and tpm_get_vendordata Christophe Ricard
@ 2016-03-20 19:34   ` Christophe Ricard
  2016-03-20 19:34   ` [PATCH 07/12] devicetree: Add Trusted Computing Group " Christophe Ricard
                     ` (8 subsequent siblings)
  14 siblings, 0 replies; 39+ messages in thread
From: Christophe Ricard @ 2016-03-20 19:34 UTC (permalink / raw)
  To: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

Add missing vendor to vendor-prefix.txt

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 72e2c5a..6c3d970 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -113,6 +113,7 @@ ibm	International Business Machines (IBM)
 idt	Integrated Device Technologies, Inc.
 iom	Iomega Corporation
 img	Imagination Technologies Ltd.
+infineon Infineon Technologies
 ingenic	Ingenic Semiconductor
 innolux	Innolux Corporation
 intel	Intel Corporation
-- 
2.5.0


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 07/12] devicetree: Add Trusted Computing Group to vendor-prefix.txt
       [not found] ` <1458502483-16887-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (5 preceding siblings ...)
  2016-03-20 19:34   ` [PATCH 06/12] devicetree: Add infineon to vendor-prefix.txt Christophe Ricard
@ 2016-03-20 19:34   ` Christophe Ricard
  2016-03-20 19:34   ` [PATCH 08/12] tpm/tpm_tis: Split tpm_tis driver into a core and TCG TIS compliant phy Christophe Ricard
                     ` (7 subsequent siblings)
  14 siblings, 0 replies; 39+ messages in thread
From: Christophe Ricard @ 2016-03-20 19:34 UTC (permalink / raw)
  To: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

Add missing vendor to vendor-prefix.txt.

Trusted Computing Group design common specifications for
TPM (Trusted Platform Module) vendors.
TCG designates a TPM answering to a public specification.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 6c3d970..717bae9 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -230,6 +230,7 @@ stericsson	ST-Ericsson
 synology	Synology, Inc.
 tbs	TBS Technologies
 tcl	Toby Churchill Ltd.
+tcg	Trusted Computing Group
 technologic	Technologic Systems
 thine	THine Electronics, Inc.
 ti	Texas Instruments
-- 
2.5.0


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 08/12] tpm/tpm_tis: Split tpm_tis driver into a core and TCG TIS compliant phy
       [not found] ` <1458502483-16887-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (6 preceding siblings ...)
  2016-03-20 19:34   ` [PATCH 07/12] devicetree: Add Trusted Computing Group " Christophe Ricard
@ 2016-03-20 19:34   ` Christophe Ricard
       [not found]     ` <1458502483-16887-9-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2016-03-20 19:34   ` [PATCH 09/12] tpm/tpm_tis: Rework interrupt management for phy compatibility Christophe Ricard
                     ` (6 subsequent siblings)
  14 siblings, 1 reply; 39+ messages in thread
From: Christophe Ricard @ 2016-03-20 19:34 UTC (permalink / raw)
  To: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, Peter Huewe,
	benoit.houyere-qxv4g6HH51o

To avoid code duplication between the old tpm_tis and the new and future
native tcg tis driver(ie: spi, i2c...), the tpm_tis driver was reworked,
so that all common logic is extracted and can be reused from all drivers.

The core methods can also be used from other TIS like drivers.

Signed-off-by: Peter Huewe <peter.huewe-d0qZbvYSIPpWk0Htik3J/w@public.gmane.org>
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/char/tpm/Makefile       |   2 +-
 drivers/char/tpm/tpm.h          |   2 +
 drivers/char/tpm/tpm_tis.c      | 803 +++-------------------------------------
 drivers/char/tpm/tpm_tis_core.c | 728 ++++++++++++++++++++++++++++++++++++
 drivers/char/tpm/tpm_tis_core.h | 166 +++++++++
 include/linux/tpm.h             |   4 +
 6 files changed, 954 insertions(+), 751 deletions(-)
 create mode 100644 drivers/char/tpm/tpm_tis_core.c
 create mode 100644 drivers/char/tpm/tpm_tis_core.h

diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 56e8f1f..c6a4cea 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the kernel tpm device drivers.
 #
 obj-$(CONFIG_TCG_TPM) += tpm.o
-tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o
+tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o tpm_tis_core.o
 tpm-$(CONFIG_ACPI) += tpm_ppi.o
 
 ifdef CONFIG_ACPI
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 6a973b9..3ec04f4 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -142,6 +142,7 @@ struct tpm_vendor_specific {
 
 	int region_size;
 	int have_region;
+	bool itpm;
 
 	struct list_head list;
 	int locality;
@@ -149,6 +150,7 @@ struct tpm_vendor_specific {
 	bool timeout_adjusted;
 	unsigned long duration[3]; /* jiffies */
 	bool duration_adjusted;
+	bool irq_tested;
 	void *priv;
 
 	wait_queue_head_t read_queue;
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 607fa3f..eb86667 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -19,6 +19,7 @@
  * published by the Free Software Foundation, version 2 of the
  * License.
  */
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -29,40 +30,49 @@
 #include <linux/acpi.h>
 #include <linux/freezer.h>
 #include "tpm.h"
+#include "tpm_tis_core.h"
 
-enum tis_access {
-	TPM_ACCESS_VALID = 0x80,
-	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
-	TPM_ACCESS_REQUEST_PENDING = 0x04,
-	TPM_ACCESS_REQUEST_USE = 0x02,
-};
+static int read_mem_bytes(struct tpm_chip *chip, u32 addr, size_t len, u8 size,
+			  u8 *result)
+{
+	int i;
 
-enum tis_status {
-	TPM_STS_VALID = 0x80,
-	TPM_STS_COMMAND_READY = 0x40,
-	TPM_STS_GO = 0x20,
-	TPM_STS_DATA_AVAIL = 0x10,
-	TPM_STS_DATA_EXPECT = 0x08,
-};
+	switch (size) {
+	case 4:
+		*(u32 *)result = ioread32(chip->vendor.iobase + addr);
+	break;
+	case 2:
+		*(u16 *)result = ioread16(chip->vendor.iobase + addr);
+	break;
+	case 1:
+	default:
+		for (i = 0; i < len; i++)
+			result[i] = ioread8(chip->vendor.iobase + addr);
+	}
 
-enum tis_int_flags {
-	TPM_GLOBAL_INT_ENABLE = 0x80000000,
-	TPM_INTF_BURST_COUNT_STATIC = 0x100,
-	TPM_INTF_CMD_READY_INT = 0x080,
-	TPM_INTF_INT_EDGE_FALLING = 0x040,
-	TPM_INTF_INT_EDGE_RISING = 0x020,
-	TPM_INTF_INT_LEVEL_LOW = 0x010,
-	TPM_INTF_INT_LEVEL_HIGH = 0x008,
-	TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
-	TPM_INTF_STS_VALID_INT = 0x002,
-	TPM_INTF_DATA_AVAIL_INT = 0x001,
-};
+	return 0;
+}
 
-enum tis_defaults {
-	TIS_MEM_LEN = 0x5000,
-	TIS_SHORT_TIMEOUT = 750,	/* ms */
-	TIS_LONG_TIMEOUT = 2000,	/* 2 sec */
-};
+static int write_mem_bytes(struct tpm_chip *chip, u32 addr, size_t len, u8 size,
+			   u8 *value)
+{
+	int i;
+
+	switch (size) {
+	case 4:
+		iowrite32(*(u32 *)value, chip->vendor.iobase + addr);
+	break;
+	case 2:
+		iowrite16(*(u16 *)value, chip->vendor.iobase + addr);
+	break;
+	case 1:
+	default:
+		for (i = 0 ; i < len; i++)
+			iowrite8(value[i], chip->vendor.iobase + addr);
+	}
+
+	return 0;
+}
 
 struct tpm_info {
 	struct resource res;
@@ -73,38 +83,14 @@ struct tpm_info {
 	int irq;
 };
 
-/* Some timeout values are needed before it is known whether the chip is
- * TPM 1.0 or TPM 2.0.
- */
-#define TIS_TIMEOUT_A_MAX	max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_A)
-#define TIS_TIMEOUT_B_MAX	max(TIS_LONG_TIMEOUT, TPM2_TIMEOUT_B)
-#define TIS_TIMEOUT_C_MAX	max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_C)
-#define TIS_TIMEOUT_D_MAX	max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_D)
-
-#define	TPM_ACCESS(l)			(0x0000 | ((l) << 12))
-#define	TPM_INT_ENABLE(l)		(0x0008 | ((l) << 12))
-#define	TPM_INT_VECTOR(l)		(0x000C | ((l) << 12))
-#define	TPM_INT_STATUS(l)		(0x0010 | ((l) << 12))
-#define	TPM_INTF_CAPS(l)		(0x0014 | ((l) << 12))
-#define	TPM_STS(l)			(0x0018 | ((l) << 12))
-#define	TPM_STS3(l)			(0x001b | ((l) << 12))
-#define	TPM_DATA_FIFO(l)		(0x0024 | ((l) << 12))
-
-#define	TPM_DID_VID(l)			(0x0F00 | ((l) << 12))
-#define	TPM_RID(l)			(0x0F04 | ((l) << 12))
-
-struct priv_data {
-	bool irq_tested;
-};
-
 #if defined(CONFIG_PNP) && defined(CONFIG_ACPI)
 static int has_hid(struct acpi_device *dev, const char *hid)
 {
 	struct acpi_hardware_id *id;
 
 	list_for_each_entry(id, &dev->pnp.ids, list)
-		if (!strcmp(hid, id->id))
-			return 1;
+	if (!strcmp(hid, id->id))
+		return 1;
 
 	return 0;
 }
@@ -120,409 +106,10 @@ static inline int is_itpm(struct acpi_device *dev)
 }
 #endif
 
-/* Before we attempt to access the TPM we must see that the valid bit is set.
- * The specification says that this bit is 0 at reset and remains 0 until the
- * 'TPM has gone through its self test and initialization and has established
- * correct values in the other bits.' */
-static int wait_startup(struct tpm_chip *chip, int l)
-{
-	unsigned long stop = jiffies + chip->vendor.timeout_a;
-	do {
-		if (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
-		    TPM_ACCESS_VALID)
-			return 0;
-		msleep(TPM_TIMEOUT);
-	} while (time_before(jiffies, stop));
-	return -1;
-}
-
-static int check_locality(struct tpm_chip *chip, int l)
-{
-	if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
-	     (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
-	    (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
-		return chip->vendor.locality = l;
-
-	return -1;
-}
-
-static void release_locality(struct tpm_chip *chip, int l, int force)
-{
-	if (force || (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
-		      (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
-	    (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID))
-		iowrite8(TPM_ACCESS_ACTIVE_LOCALITY,
-			 chip->vendor.iobase + TPM_ACCESS(l));
-}
-
-static int request_locality(struct tpm_chip *chip, int l)
-{
-	unsigned long stop, timeout;
-	long rc;
-
-	if (check_locality(chip, l) >= 0)
-		return l;
-
-	iowrite8(TPM_ACCESS_REQUEST_USE,
-		 chip->vendor.iobase + TPM_ACCESS(l));
-
-	stop = jiffies + chip->vendor.timeout_a;
-
-	if (chip->vendor.irq) {
-again:
-		timeout = stop - jiffies;
-		if ((long)timeout <= 0)
-			return -1;
-		rc = wait_event_interruptible_timeout(chip->vendor.int_queue,
-						      (check_locality
-						       (chip, l) >= 0),
-						      timeout);
-		if (rc > 0)
-			return l;
-		if (rc == -ERESTARTSYS && freezing(current)) {
-			clear_thread_flag(TIF_SIGPENDING);
-			goto again;
-		}
-	} else {
-		/* wait for burstcount */
-		do {
-			if (check_locality(chip, l) >= 0)
-				return l;
-			msleep(TPM_TIMEOUT);
-		}
-		while (time_before(jiffies, stop));
-	}
-	return -1;
-}
-
-static u8 tpm_tis_status(struct tpm_chip *chip)
-{
-	return ioread8(chip->vendor.iobase +
-		       TPM_STS(chip->vendor.locality));
-}
-
-static void tpm_tis_ready(struct tpm_chip *chip)
-{
-	/* this causes the current command to be aborted */
-	iowrite8(TPM_STS_COMMAND_READY,
-		 chip->vendor.iobase + TPM_STS(chip->vendor.locality));
-}
-
-static int get_burstcount(struct tpm_chip *chip)
-{
-	unsigned long stop;
-	int burstcnt;
-
-	/* wait for burstcount */
-	/* which timeout value, spec has 2 answers (c & d) */
-	stop = jiffies + chip->vendor.timeout_d;
-	do {
-		burstcnt = ioread8(chip->vendor.iobase +
-				   TPM_STS(chip->vendor.locality) + 1);
-		burstcnt += ioread8(chip->vendor.iobase +
-				    TPM_STS(chip->vendor.locality) +
-				    2) << 8;
-		if (burstcnt)
-			return burstcnt;
-		msleep(TPM_TIMEOUT);
-	} while (time_before(jiffies, stop));
-	return -EBUSY;
-}
-
-static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
-{
-	int size = 0, burstcnt;
-	while (size < count &&
-	       wait_for_tpm_stat(chip,
-				 TPM_STS_DATA_AVAIL | TPM_STS_VALID,
-				 chip->vendor.timeout_c,
-				 &chip->vendor.read_queue, true)
-	       == 0) {
-		burstcnt = get_burstcount(chip);
-		for (; burstcnt > 0 && size < count; burstcnt--)
-			buf[size++] = ioread8(chip->vendor.iobase +
-					      TPM_DATA_FIFO(chip->vendor.
-							    locality));
-	}
-	return size;
-}
-
-static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
-{
-	int size = 0;
-	int expected, status;
-
-	if (count < TPM_HEADER_SIZE) {
-		size = -EIO;
-		goto out;
-	}
-
-	/* read first 10 bytes, including tag, paramsize, and result */
-	if ((size =
-	     recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) {
-		dev_err(&chip->dev, "Unable to read header\n");
-		goto out;
-	}
-
-	expected = be32_to_cpu(*(__be32 *) (buf + 2));
-	if (expected > count) {
-		size = -EIO;
-		goto out;
-	}
-
-	if ((size +=
-	     recv_data(chip, &buf[TPM_HEADER_SIZE],
-		       expected - TPM_HEADER_SIZE)) < expected) {
-		dev_err(&chip->dev, "Unable to read remainder of result\n");
-		size = -ETIME;
-		goto out;
-	}
-
-	wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
-			  &chip->vendor.int_queue, false);
-	status = tpm_tis_status(chip);
-	if (status & TPM_STS_DATA_AVAIL) {	/* retry? */
-		dev_err(&chip->dev, "Error left over data\n");
-		size = -EIO;
-		goto out;
-	}
-
-out:
-	tpm_tis_ready(chip);
-	release_locality(chip, chip->vendor.locality, 0);
-	return size;
-}
-
 static bool itpm;
 module_param(itpm, bool, 0444);
 MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)");
 
-/*
- * If interrupts are used (signaled by an irq set in the vendor structure)
- * tpm.c can skip polling for the data to be available as the interrupt is
- * waited for here
- */
-static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
-{
-	int rc, status, burstcnt;
-	size_t count = 0;
-
-	if (request_locality(chip, 0) < 0)
-		return -EBUSY;
-
-	status = tpm_tis_status(chip);
-	if ((status & TPM_STS_COMMAND_READY) == 0) {
-		tpm_tis_ready(chip);
-		if (wait_for_tpm_stat
-		    (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
-		     &chip->vendor.int_queue, false) < 0) {
-			rc = -ETIME;
-			goto out_err;
-		}
-	}
-
-	while (count < len - 1) {
-		burstcnt = get_burstcount(chip);
-		for (; burstcnt > 0 && count < len - 1; burstcnt--) {
-			iowrite8(buf[count], chip->vendor.iobase +
-				 TPM_DATA_FIFO(chip->vendor.locality));
-			count++;
-		}
-
-		wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
-				  &chip->vendor.int_queue, false);
-		status = tpm_tis_status(chip);
-		if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) {
-			rc = -EIO;
-			goto out_err;
-		}
-	}
-
-	/* write last byte */
-	iowrite8(buf[count],
-		 chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality));
-	wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
-			  &chip->vendor.int_queue, false);
-	status = tpm_tis_status(chip);
-	if ((status & TPM_STS_DATA_EXPECT) != 0) {
-		rc = -EIO;
-		goto out_err;
-	}
-
-	return 0;
-
-out_err:
-	tpm_tis_ready(chip);
-	release_locality(chip, chip->vendor.locality, 0);
-	return rc;
-}
-
-static void disable_interrupts(struct tpm_chip *chip)
-{
-	u32 intmask;
-
-	intmask =
-	    ioread32(chip->vendor.iobase +
-		     TPM_INT_ENABLE(chip->vendor.locality));
-	intmask &= ~TPM_GLOBAL_INT_ENABLE;
-	iowrite32(intmask,
-		  chip->vendor.iobase +
-		  TPM_INT_ENABLE(chip->vendor.locality));
-	devm_free_irq(&chip->dev, chip->vendor.irq, chip);
-	chip->vendor.irq = 0;
-}
-
-/*
- * If interrupts are used (signaled by an irq set in the vendor structure)
- * tpm.c can skip polling for the data to be available as the interrupt is
- * waited for here
- */
-static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len)
-{
-	int rc;
-	u32 ordinal;
-	unsigned long dur;
-
-	rc = tpm_tis_send_data(chip, buf, len);
-	if (rc < 0)
-		return rc;
-
-	/* go and do it */
-	iowrite8(TPM_STS_GO,
-		 chip->vendor.iobase + TPM_STS(chip->vendor.locality));
-
-	if (chip->vendor.irq) {
-		ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
-
-		if (chip->flags & TPM_CHIP_FLAG_TPM2)
-			dur = tpm2_calc_ordinal_duration(chip, ordinal);
-		else
-			dur = tpm_calc_ordinal_duration(chip, ordinal);
-
-		if (wait_for_tpm_stat
-		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,
-		     &chip->vendor.read_queue, false) < 0) {
-			rc = -ETIME;
-			goto out_err;
-		}
-	}
-	return len;
-out_err:
-	tpm_tis_ready(chip);
-	release_locality(chip, chip->vendor.locality, 0);
-	return rc;
-}
-
-static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
-{
-	int rc, irq;
-	struct priv_data *priv = chip->vendor.priv;
-
-	if (!chip->vendor.irq || priv->irq_tested)
-		return tpm_tis_send_main(chip, buf, len);
-
-	/* Verify receipt of the expected IRQ */
-	irq = chip->vendor.irq;
-	chip->vendor.irq = 0;
-	rc = tpm_tis_send_main(chip, buf, len);
-	chip->vendor.irq = irq;
-	if (!priv->irq_tested)
-		msleep(1);
-	if (!priv->irq_tested)
-		disable_interrupts(chip);
-	priv->irq_tested = true;
-	return rc;
-}
-
-struct tis_vendor_timeout_override {
-	u32 did_vid;
-	unsigned long timeout_us[4];
-};
-
-static const struct tis_vendor_timeout_override vendor_timeout_overrides[] = {
-	/* Atmel 3204 */
-	{ 0x32041114, { (TIS_SHORT_TIMEOUT*1000), (TIS_LONG_TIMEOUT*1000),
-			(TIS_SHORT_TIMEOUT*1000), (TIS_SHORT_TIMEOUT*1000) } },
-};
-
-static bool tpm_tis_update_timeouts(struct tpm_chip *chip,
-				    unsigned long *timeout_cap)
-{
-	int i;
-	u32 did_vid;
-
-	did_vid = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
-
-	for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) {
-		if (vendor_timeout_overrides[i].did_vid != did_vid)
-			continue;
-		memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us,
-		       sizeof(vendor_timeout_overrides[i].timeout_us));
-		return true;
-	}
-
-	return false;
-}
-
-/*
- * Early probing for iTPM with STS_DATA_EXPECT flaw.
- * Try sending command without itpm flag set and if that
- * fails, repeat with itpm flag set.
- */
-static int probe_itpm(struct tpm_chip *chip)
-{
-	int rc = 0;
-	u8 cmd_getticks[] = {
-		0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a,
-		0x00, 0x00, 0x00, 0xf1
-	};
-	size_t len = sizeof(cmd_getticks);
-	bool rem_itpm = itpm;
-	u16 vendor = ioread16(chip->vendor.iobase + TPM_DID_VID(0));
-
-	/* probe only iTPMS */
-	if (vendor != TPM_VID_INTEL)
-		return 0;
-
-	itpm = false;
-
-	rc = tpm_tis_send_data(chip, cmd_getticks, len);
-	if (rc == 0)
-		goto out;
-
-	tpm_tis_ready(chip);
-	release_locality(chip, chip->vendor.locality, 0);
-
-	itpm = true;
-
-	rc = tpm_tis_send_data(chip, cmd_getticks, len);
-	if (rc == 0) {
-		dev_info(&chip->dev, "Detected an iTPM.\n");
-		rc = 1;
-	} else
-		rc = -EFAULT;
-
-out:
-	itpm = rem_itpm;
-	tpm_tis_ready(chip);
-	release_locality(chip, chip->vendor.locality, 0);
-
-	return rc;
-}
-
-static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status)
-{
-	switch (chip->vendor.manufacturer_id) {
-	case TPM_VID_WINBOND:
-		return ((status == TPM_STS_VALID) ||
-			(status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)));
-	case TPM_VID_STM:
-		return (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY));
-	default:
-		return (status == TPM_STS_COMMAND_READY);
-	}
-}
-
 static const struct tpm_class_ops tpm_tis = {
 	.status = tpm_tis_status,
 	.recv = tpm_tis_recv,
@@ -532,153 +119,24 @@ static const struct tpm_class_ops tpm_tis = {
 	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
 	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
 	.req_canceled = tpm_tis_req_canceled,
+	.read_bytes = read_mem_bytes,
+	.write_bytes = write_mem_bytes,
 };
 
-static irqreturn_t tis_int_handler(int dummy, void *dev_id)
-{
-	struct tpm_chip *chip = dev_id;
-	u32 interrupt;
-	int i;
-
-	interrupt = ioread32(chip->vendor.iobase +
-			     TPM_INT_STATUS(chip->vendor.locality));
-
-	if (interrupt == 0)
-		return IRQ_NONE;
-
-	((struct priv_data *)chip->vendor.priv)->irq_tested = true;
-	if (interrupt & TPM_INTF_DATA_AVAIL_INT)
-		wake_up_interruptible(&chip->vendor.read_queue);
-	if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
-		for (i = 0; i < 5; i++)
-			if (check_locality(chip, i) >= 0)
-				break;
-	if (interrupt &
-	    (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT |
-	     TPM_INTF_CMD_READY_INT))
-		wake_up_interruptible(&chip->vendor.int_queue);
-
-	/* Clear interrupts handled with TPM_EOI */
-	iowrite32(interrupt,
-		  chip->vendor.iobase +
-		  TPM_INT_STATUS(chip->vendor.locality));
-	ioread32(chip->vendor.iobase + TPM_INT_STATUS(chip->vendor.locality));
-	return IRQ_HANDLED;
-}
-
-/* Register the IRQ and issue a command that will cause an interrupt. If an
- * irq is seen then leave the chip setup for IRQ operation, otherwise reverse
- * everything and leave in polling mode. Returns 0 on success.
- */
-static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
-				    int flags, int irq)
-{
-	struct priv_data *priv = chip->vendor.priv;
-	u8 original_int_vec;
-
-	if (devm_request_irq(&chip->dev, irq, tis_int_handler, flags,
-			     dev_name(&chip->dev), chip) != 0) {
-		dev_info(&chip->dev, "Unable to request irq: %d for probe\n",
-			 irq);
-		return -1;
-	}
-	chip->vendor.irq = irq;
-
-	original_int_vec = ioread8(chip->vendor.iobase +
-				   TPM_INT_VECTOR(chip->vendor.locality));
-	iowrite8(irq,
-		 chip->vendor.iobase + TPM_INT_VECTOR(chip->vendor.locality));
-
-	/* Clear all existing */
-	iowrite32(ioread32(chip->vendor.iobase +
-			   TPM_INT_STATUS(chip->vendor.locality)),
-		  chip->vendor.iobase + TPM_INT_STATUS(chip->vendor.locality));
-
-	/* Turn on */
-	iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
-		  chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality));
-
-	priv->irq_tested = false;
-
-	/* Generate an interrupt by having the core call through to
-	 * tpm_tis_send
-	 */
-	if (chip->flags & TPM_CHIP_FLAG_TPM2)
-		tpm2_gen_interrupt(chip);
-	else
-		tpm_gen_interrupt(chip);
-
-	/* tpm_tis_send will either confirm the interrupt is working or it
-	 * will call disable_irq which undoes all of the above.
-	 */
-	if (!chip->vendor.irq) {
-		iowrite8(original_int_vec,
-			 chip->vendor.iobase +
-			     TPM_INT_VECTOR(chip->vendor.locality));
-		return 1;
-	}
-
-	return 0;
-}
-
-/* Try to find the IRQ the TPM is using. This is for legacy x86 systems that
- * do not have ACPI/etc. We typically expect the interrupt to be declared if
- * present.
- */
-static void tpm_tis_probe_irq(struct tpm_chip *chip, u32 intmask)
-{
-	u8 original_int_vec;
-	int i;
-
-	original_int_vec = ioread8(chip->vendor.iobase +
-				   TPM_INT_VECTOR(chip->vendor.locality));
-
-	if (!original_int_vec) {
-		if (IS_ENABLED(CONFIG_X86))
-			for (i = 3; i <= 15; i++)
-				if (!tpm_tis_probe_irq_single(chip, intmask, 0,
-							      i))
-					return;
-	} else if (!tpm_tis_probe_irq_single(chip, intmask, 0,
-					     original_int_vec))
-		return;
-}
-
 static bool interrupts = true;
 module_param(interrupts, bool, 0444);
 MODULE_PARM_DESC(interrupts, "Enable interrupts");
 
-static void tpm_tis_remove(struct tpm_chip *chip)
-{
-	if (chip->flags & TPM_CHIP_FLAG_TPM2)
-		tpm2_shutdown(chip, TPM2_SU_CLEAR);
-
-	iowrite32(~TPM_GLOBAL_INT_ENABLE &
-		  ioread32(chip->vendor.iobase +
-			   TPM_INT_ENABLE(chip->vendor.
-					  locality)),
-		  chip->vendor.iobase +
-		  TPM_INT_ENABLE(chip->vendor.locality));
-	release_locality(chip, chip->vendor.locality, 1);
-}
-
 static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
 			acpi_handle acpi_dev_handle)
 {
-	u32 vendor, intfcaps, intmask;
-	int rc, probe;
+	int ret, irq = tpm_info->irq;
 	struct tpm_chip *chip;
-	struct priv_data *priv;
-
-	priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL);
-	if (priv == NULL)
-		return -ENOMEM;
 
 	chip = tpmm_chip_alloc(dev, &tpm_tis);
 	if (IS_ERR(chip))
 		return PTR_ERR(chip);
 
-	tpm_set_vendordata(chip, priv);
 #ifdef CONFIG_ACPI
 	chip->acpi_dev_handle = acpi_dev_handle;
 #endif
@@ -687,177 +145,22 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
 	if (IS_ERR(chip->vendor.iobase))
 		return PTR_ERR(chip->vendor.iobase);
 
-	/* Maximum timeouts */
-	chip->vendor.timeout_a = TIS_TIMEOUT_A_MAX;
-	chip->vendor.timeout_b = TIS_TIMEOUT_B_MAX;
-	chip->vendor.timeout_c = TIS_TIMEOUT_C_MAX;
-	chip->vendor.timeout_d = TIS_TIMEOUT_D_MAX;
-
-	if (wait_startup(chip, 0) != 0) {
-		rc = -ENODEV;
-		goto out_err;
-	}
+	chip->vendor.itpm = itpm;
 
-	/* Take control of the TPM's interrupt hardware and shut it off */
-	intmask = ioread32(chip->vendor.iobase +
-			   TPM_INT_ENABLE(chip->vendor.locality));
-	intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
-		   TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
-	intmask &= ~TPM_GLOBAL_INT_ENABLE;
-	iowrite32(intmask,
-		  chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality));
-
-	if (request_locality(chip, 0) != 0) {
-		rc = -ENODEV;
-		goto out_err;
-	}
+	if (!interrupts)
+		irq = -1;
 
-	rc = tpm2_probe(chip);
-	if (rc)
+	ret = tpm_tis_init_core(dev, chip, irq, IRQF_SHARED);
+	if (ret < 0)
 		goto out_err;
 
-	vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
-	chip->vendor.manufacturer_id = vendor;
-
-	dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n",
-		 (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2",
-		 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
-
-	if (!itpm) {
-		probe = probe_itpm(chip);
-		if (probe < 0) {
-			rc = -ENODEV;
-			goto out_err;
-		}
-		itpm = !!probe;
-	}
-
-	if (itpm)
-		dev_info(dev, "Intel iTPM workaround enabled\n");
-
-
-	/* Figure out the capabilities */
-	intfcaps =
-	    ioread32(chip->vendor.iobase +
-		     TPM_INTF_CAPS(chip->vendor.locality));
-	dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
-		intfcaps);
-	if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
-		dev_dbg(dev, "\tBurst Count Static\n");
-	if (intfcaps & TPM_INTF_CMD_READY_INT)
-		dev_dbg(dev, "\tCommand Ready Int Support\n");
-	if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
-		dev_dbg(dev, "\tInterrupt Edge Falling\n");
-	if (intfcaps & TPM_INTF_INT_EDGE_RISING)
-		dev_dbg(dev, "\tInterrupt Edge Rising\n");
-	if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
-		dev_dbg(dev, "\tInterrupt Level Low\n");
-	if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
-		dev_dbg(dev, "\tInterrupt Level High\n");
-	if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
-		dev_dbg(dev, "\tLocality Change Int Support\n");
-	if (intfcaps & TPM_INTF_STS_VALID_INT)
-		dev_dbg(dev, "\tSts Valid Int Support\n");
-	if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
-		dev_dbg(dev, "\tData Avail Int Support\n");
-
-	/* Very early on issue a command to the TPM in polling mode to make
-	 * sure it works. May as well use that command to set the proper
-	 *  timeouts for the driver.
-	 */
-	if (tpm_get_timeouts(chip)) {
-		dev_err(dev, "Could not get TPM timeouts and durations\n");
-		rc = -ENODEV;
-		goto out_err;
-	}
+	return ret;
 
-	/* INTERRUPT Setup */
-	init_waitqueue_head(&chip->vendor.read_queue);
-	init_waitqueue_head(&chip->vendor.int_queue);
-	if (interrupts && tpm_info->irq != -1) {
-		if (tpm_info->irq) {
-			tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
-						 tpm_info->irq);
-			if (!chip->vendor.irq)
-				dev_err(&chip->dev, FW_BUG
-					"TPM interrupt not working, polling instead\n");
-		} else
-			tpm_tis_probe_irq(chip, intmask);
-	}
-
-	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
-		rc = tpm2_do_selftest(chip);
-		if (rc == TPM2_RC_INITIALIZE) {
-			dev_warn(dev, "Firmware has not started TPM\n");
-			rc  = tpm2_startup(chip, TPM2_SU_CLEAR);
-			if (!rc)
-				rc = tpm2_do_selftest(chip);
-		}
-
-		if (rc) {
-			dev_err(dev, "TPM self test failed\n");
-			if (rc > 0)
-				rc = -ENODEV;
-			goto out_err;
-		}
-	} else {
-		if (tpm_do_selftest(chip)) {
-			dev_err(dev, "TPM self test failed\n");
-			rc = -ENODEV;
-			goto out_err;
-		}
-	}
-
-	return tpm_chip_register(chip);
 out_err:
 	tpm_tis_remove(chip);
-	return rc;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
-{
-	u32 intmask;
-
-	/* reenable interrupts that device may have lost or
-	   BIOS/firmware may have disabled */
-	iowrite8(chip->vendor.irq, chip->vendor.iobase +
-		 TPM_INT_VECTOR(chip->vendor.locality));
-
-	intmask =
-	    ioread32(chip->vendor.iobase +
-		     TPM_INT_ENABLE(chip->vendor.locality));
-
-	intmask |= TPM_INTF_CMD_READY_INT
-	    | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
-	    | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE;
-
-	iowrite32(intmask,
-		  chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality));
+	return ret;
 }
 
-static int tpm_tis_resume(struct device *dev)
-{
-	struct tpm_chip *chip = dev_get_drvdata(dev);
-	int ret;
-
-	if (chip->vendor.irq)
-		tpm_tis_reenable_interrupts(chip);
-
-	ret = tpm_pm_resume(dev);
-	if (ret)
-		return ret;
-
-	/* TPM 1.2 requires self-test on resume. This function actually returns
-	 * an error code but for unknown reason it isn't handled.
-	 */
-	if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
-		tpm_do_selftest(chip);
-
-	return 0;
-}
-#endif
-
 static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume);
 
 static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
@@ -919,7 +222,7 @@ static struct pnp_driver tis_pnp_driver = {
 	},
 };
 
-#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2
+#define TIS_HID_USR_IDX (sizeof(tpm_pnp_tbl) / sizeof(struct pnp_device_id) - 2)
 module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
 		    sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
 MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
new file mode 100644
index 0000000..b9cc61f
--- /dev/null
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -0,0 +1,728 @@
+/*
+ * Copyright (C) 2005, 2006 IBM Corporation
+ * Copyright (C) 2014, 2015 Intel Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert-aZOuKsOsJu3MbYB6QlFGEg@public.gmane.org>
+ * Kylene Hall <kjhall-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
+ *
+ * Maintained by: <tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This device driver implements the TPM interface as defined in
+ * the TCG TPM Interface Spec version 1.2, revision 1.0.
+ *
+ * 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 the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pnp.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/acpi.h>
+#include <linux/freezer.h>
+#include "tpm.h"
+#include "tpm_tis_core.h"
+
+struct tpm_info {
+	struct resource res;
+	/* irq > 0 means: use irq $irq;
+	 * irq = 0 means: autoprobe for an irq;
+	 * irq = -1 means: no irq support
+	 */
+	int irq;
+};
+
+/* Before we attempt to access the TPM we must see that the valid bit is set.
+ * The specification says that this bit is 0 at reset and remains 0 until the
+ * 'TPM has gone through its self test and initialization and has established
+ * correct values in the other bits.'
+ */
+static int wait_startup(struct tpm_chip *chip, int l)
+{
+	unsigned long stop = jiffies + chip->vendor.timeout_a;
+
+	do {
+		if (tpm_read_byte(chip, TPM_ACCESS(l)) & TPM_ACCESS_VALID)
+			return 0;
+		msleep(TPM_TIMEOUT);
+	} while (time_before(jiffies, stop));
+	return -1;
+}
+
+static int check_locality(struct tpm_chip *chip, int l)
+{
+	if ((tpm_read_byte(chip, TPM_ACCESS(l)) &
+	     (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
+	    (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
+		return chip->vendor.locality = l;
+
+	return -1;
+}
+
+static void release_locality(struct tpm_chip *chip, int l, int force)
+{
+	if (force || (tpm_read_byte(chip, TPM_ACCESS(l)) &
+		      (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
+	    (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID))
+		tpm_write_byte(chip, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
+}
+
+static int request_locality(struct tpm_chip *chip, int l)
+{
+	unsigned long stop, timeout;
+	long rc;
+
+	if (check_locality(chip, l) >= 0)
+		return l;
+
+	tpm_write_byte(chip, TPM_ACCESS(l), TPM_ACCESS_REQUEST_USE);
+
+	stop = jiffies + chip->vendor.timeout_a;
+
+	if (chip->vendor.irq) {
+again:
+		timeout = stop - jiffies;
+		if ((long)timeout <= 0)
+			return -1;
+		rc = wait_event_interruptible_timeout(chip->vendor.int_queue,
+						      (check_locality
+						       (chip, l) >= 0),
+						      timeout);
+		if (rc > 0)
+			return l;
+		if (rc == -ERESTARTSYS && freezing(current)) {
+			clear_thread_flag(TIF_SIGPENDING);
+			goto again;
+		}
+	} else {
+		/* wait for burstcount */
+		do {
+			if (check_locality(chip, l) >= 0)
+				return l;
+			msleep(TPM_TIMEOUT);
+		} while (time_before(jiffies, stop));
+	}
+	return -1;
+}
+
+u8 tpm_tis_status(struct tpm_chip *chip)
+{
+	return tpm_read_byte(chip, TPM_STS(chip->vendor.locality));
+}
+EXPORT_SYMBOL(tpm_tis_status);
+
+void tpm_tis_ready(struct tpm_chip *chip)
+{
+	/* this causes the current command to be aborted */
+	tpm_write_byte(chip, TPM_STS(chip->vendor.locality),
+		       TPM_STS_COMMAND_READY);
+}
+EXPORT_SYMBOL(tpm_tis_ready);
+
+static int get_burstcount(struct tpm_chip *chip)
+{
+	unsigned long stop;
+	int burstcnt, status;
+	u8 temp;
+
+	/* wait for burstcount */
+	/* which timeout value, spec has 2 answers (c & d) */
+	stop = jiffies + chip->vendor.timeout_d;
+	do {
+		status = tpm_read_bytes(chip, TPM_STS(chip->vendor.locality) +
+					1, 1, &temp);
+		if (status < 0)
+			return -EBUSY;
+
+		burstcnt = temp;
+		status = tpm_read_bytes(chip, TPM_STS(chip->vendor.locality) +
+					2, 1, &temp);
+		if (status < 0)
+			return -EBUSY;
+
+		burstcnt |= temp << 8;
+
+		if (burstcnt)
+			return burstcnt;
+		msleep(TPM_TIMEOUT);
+	} while (time_before(jiffies, stop));
+	return -EBUSY;
+}
+
+static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	int size = 0, burstcnt, transfer_size, ret;
+
+	while (size < count &&
+		wait_for_tpm_stat(chip,
+				 TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+				 chip->vendor.timeout_c,
+				 &chip->vendor.read_queue, true) == 0) {
+		burstcnt = get_burstcount(chip);
+
+		transfer_size = min_t(size_t, (count - size), burstcnt);
+
+		ret = tpm_read_bytes(chip, TPM_DATA_FIFO(chip->vendor.locality),
+				     transfer_size, &buf[size]);
+		if (ret < 0)
+			return ret;
+
+		size += transfer_size;
+	}
+
+	return size;
+}
+
+int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	int size = 0;
+	int expected, status;
+
+	if (count < TPM_HEADER_SIZE) {
+		size = -EIO;
+		goto out;
+	}
+
+	/* read first 10 bytes, including tag, paramsize, and result */
+	size = recv_data(chip, buf, TPM_HEADER_SIZE);
+	if (size < TPM_HEADER_SIZE) {
+		dev_err(&chip->dev, "Unable to read header\n");
+		goto out;
+	}
+
+	expected = be32_to_cpu(*(__be32 *) (buf + 2));
+	if (expected > count) {
+		size = -EIO;
+		goto out;
+	}
+
+	size += recv_data(chip, &buf[TPM_HEADER_SIZE],
+			  expected - TPM_HEADER_SIZE);
+	if (size < expected) {
+		dev_err(&chip->dev, "Unable to read remainder of result\n");
+		size = -ETIME;
+		goto out;
+	}
+
+	wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+			  &chip->vendor.int_queue, false);
+	status = tpm_tis_status(chip);
+	if (status & TPM_STS_DATA_AVAIL) {	/* retry? */
+		dev_err(&chip->dev, "Error left over data\n");
+		size = -EIO;
+		goto out;
+	}
+
+out:
+	tpm_tis_ready(chip);
+	release_locality(chip, chip->vendor.locality, 0);
+	return size;
+}
+EXPORT_SYMBOL(tpm_tis_recv);
+
+/*
+ * If interrupts are used (signaled by an irq set in the vendor structure)
+ * tpm.c can skip polling for the data to be available as the interrupt is
+ * waited for here
+ */
+static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
+{
+	int rc, status, burstcnt, transfer_size;
+	size_t count = 0;
+
+	if (request_locality(chip, 0) < 0)
+		return -EBUSY;
+
+	status = tpm_tis_status(chip);
+	if ((status & TPM_STS_COMMAND_READY) == 0) {
+		tpm_tis_ready(chip);
+		if (wait_for_tpm_stat
+		    (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
+		     &chip->vendor.int_queue, false) < 0) {
+			rc = -ETIME;
+			goto out_err;
+		}
+	}
+
+	while (count < len - 1) {
+		burstcnt = get_burstcount(chip);
+		transfer_size = min_t(size_t, len - count - 1, burstcnt);
+
+		rc = tpm_write_bytes(chip, TPM_DATA_FIFO(chip->vendor.locality),
+				     transfer_size, &buf[count]);
+		if (rc < 0)
+			goto out_err;
+
+		count += transfer_size;
+
+		wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+				  &chip->vendor.int_queue, false);
+		status = tpm_tis_status(chip);
+		if (!chip->vendor.itpm && (status & TPM_STS_DATA_EXPECT) == 0) {
+			rc = -EIO;
+			goto out_err;
+		}
+	}
+
+	/* write last byte */
+	tpm_write_byte(chip, TPM_DATA_FIFO(chip->vendor.locality), buf[count]);
+	wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+			  &chip->vendor.int_queue, false);
+	status = tpm_tis_status(chip);
+	if ((status & TPM_STS_DATA_EXPECT) != 0) {
+		rc = -EIO;
+		goto out_err;
+	}
+
+	return 0;
+
+out_err:
+	tpm_tis_ready(chip);
+	release_locality(chip, chip->vendor.locality, 0);
+	return rc;
+}
+
+static void disable_interrupts(struct tpm_chip *chip)
+{
+	u32 intmask;
+
+	intmask = tpm_read_dword(chip, TPM_INT_ENABLE(chip->vendor.locality));
+	intmask &= ~TPM_GLOBAL_INT_ENABLE;
+	tpm_write_dword(chip, TPM_INT_ENABLE(chip->vendor.locality), intmask);
+	devm_free_irq(&chip->dev, chip->vendor.irq, chip);
+	chip->vendor.irq = 0;
+}
+
+/*
+ * If interrupts are used (signaled by an irq set in the vendor structure)
+ * tpm.c can skip polling for the data to be available as the interrupt is
+ * waited for here
+ */
+static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len)
+{
+	int rc;
+	u32 ordinal;
+	unsigned long dur;
+
+	rc = tpm_tis_send_data(chip, buf, len);
+	if (rc < 0)
+		return rc;
+
+	/* go and do it */
+	tpm_write_byte(chip, TPM_STS(chip->vendor.locality), TPM_STS_GO);
+
+	if (chip->vendor.irq) {
+		ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
+
+		if (chip->flags & TPM_CHIP_FLAG_TPM2)
+			dur = tpm2_calc_ordinal_duration(chip, ordinal);
+		else
+			dur = tpm_calc_ordinal_duration(chip, ordinal);
+
+		if (wait_for_tpm_stat
+		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,
+		     &chip->vendor.read_queue, false) < 0) {
+			rc = -ETIME;
+			goto out_err;
+		}
+	}
+	return len;
+out_err:
+	tpm_tis_ready(chip);
+	release_locality(chip, chip->vendor.locality, 0);
+	return rc;
+}
+
+int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
+{
+	int rc, irq;
+
+	if (!chip->vendor.irq || chip->vendor.irq_tested)
+		return tpm_tis_send_main(chip, buf, len);
+
+	/* Verify receipt of the expected IRQ */
+	irq = chip->vendor.irq;
+	chip->vendor.irq = 0;
+	rc = tpm_tis_send_main(chip, buf, len);
+	chip->vendor.irq = irq;
+	if (!chip->vendor.irq_tested)
+		msleep(1);
+	if (!chip->vendor.irq_tested)
+		disable_interrupts(chip);
+	chip->vendor.irq_tested = true;
+	return rc;
+}
+EXPORT_SYMBOL(tpm_tis_send);
+
+bool tpm_tis_update_timeouts(struct tpm_chip *chip, unsigned long *timeout_cap)
+{
+	int i;
+	u32 did_vid;
+
+	did_vid = tpm_read_dword(chip, TPM_DID_VID(0));
+
+	for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) {
+		if (vendor_timeout_overrides[i].did_vid != did_vid)
+			continue;
+		memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us,
+		       sizeof(vendor_timeout_overrides[i].timeout_us));
+		return true;
+	}
+
+	return false;
+}
+EXPORT_SYMBOL(tpm_tis_update_timeouts);
+
+/*
+ * Early probing for iTPM with STS_DATA_EXPECT flaw.
+ * Try sending command without itpm flag set and if that
+ * fails, repeat with itpm flag set.
+ */
+static int probe_itpm(struct tpm_chip *chip)
+{
+	int rc = 0;
+	u8 cmd_getticks[] = {
+		0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a,
+		0x00, 0x00, 0x00, 0xf1
+	};
+	size_t len = sizeof(cmd_getticks);
+	bool rem_itpm = chip->vendor.itpm;
+	u16 vendor = tpm_read_word(chip, TPM_DID_VID(0));
+
+	/* probe only iTPMS */
+	if (vendor != TPM_VID_INTEL)
+		return 0;
+
+	chip->vendor.itpm = false;
+
+	rc = tpm_tis_send_data(chip, cmd_getticks, len);
+	if (rc == 0)
+		goto out;
+
+	tpm_tis_ready(chip);
+	release_locality(chip, chip->vendor.locality, 0);
+
+	chip->vendor.itpm = true;
+
+	rc = tpm_tis_send_data(chip, cmd_getticks, len);
+	if (rc == 0) {
+		dev_info(&chip->dev, "Detected an iTPM.\n");
+		rc = 1;
+	} else {
+		rc = -EFAULT;
+	}
+
+out:
+	chip->vendor.itpm = rem_itpm;
+	tpm_tis_ready(chip);
+	release_locality(chip, chip->vendor.locality, 0);
+
+	return rc;
+}
+
+bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status)
+{
+	switch (chip->vendor.manufacturer_id) {
+	case TPM_VID_WINBOND:
+		return ((status == TPM_STS_VALID) ||
+			(status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)));
+	case TPM_VID_STM:
+		return (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY));
+	default:
+		return (status == TPM_STS_COMMAND_READY);
+	}
+}
+EXPORT_SYMBOL(tpm_tis_req_canceled);
+
+static irqreturn_t tis_int_handler(int dummy, void *dev_id)
+{
+	struct tpm_chip *chip = dev_id;
+	u32 interrupt;
+	int i;
+
+	interrupt = tpm_read_dword(chip, TPM_INT_STATUS(chip->vendor.locality));
+
+	if (interrupt == 0)
+		return IRQ_NONE;
+
+	chip->vendor.irq_tested = true;
+	if (interrupt & TPM_INTF_DATA_AVAIL_INT)
+		wake_up_interruptible(&chip->vendor.read_queue);
+	if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
+		for (i = 0; i < 5; i++)
+			if (check_locality(chip, i) >= 0)
+				break;
+	if (interrupt &
+	    (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT |
+	     TPM_INTF_CMD_READY_INT))
+		wake_up_interruptible(&chip->vendor.int_queue);
+
+	/* Clear interrupts handled with TPM_EOI */
+	tpm_write_dword(chip, TPM_INT_STATUS(chip->vendor.locality), interrupt);
+	tpm_read_dword(chip, TPM_INT_STATUS(chip->vendor.locality));
+	return IRQ_HANDLED;
+}
+
+/* Register the IRQ and issue a command that will cause an interrupt. If an
+ * irq is seen then leave the chip setup for IRQ operation, otherwise reverse
+ * everything and leave in polling mode. Returns 0 on success.
+ */
+static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
+				    int flags, int irq)
+{
+	u8 original_int_vec;
+
+	if (devm_request_irq(&chip->dev, irq, tis_int_handler, flags,
+			     dev_name(&chip->dev), chip) != 0) {
+		dev_info(&chip->dev, "Unable to request irq: %d for probe\n",
+			 irq);
+		return -1;
+	}
+	chip->vendor.irq = irq;
+
+	original_int_vec = tpm_read_byte(chip, TPM_INT_VECTOR(chip->vendor.locality));
+	tpm_write_byte(chip, TPM_INT_VECTOR(chip->vendor.locality), irq);
+
+	/* Clear all existing */
+	tpm_write_dword(chip, TPM_INT_STATUS(chip->vendor.locality),
+			tpm_read_dword(chip, TPM_INT_STATUS(chip->vendor.locality)));
+
+	/* Turn on */
+	tpm_write_dword(chip, TPM_INT_ENABLE(chip->vendor.locality),
+			intmask | TPM_GLOBAL_INT_ENABLE);
+
+	chip->vendor.irq_tested = false;
+
+	/* Generate an interrupt by having the core call through to
+	 * tpm_tis_send
+	 */
+	if (chip->flags & TPM_CHIP_FLAG_TPM2)
+		tpm2_gen_interrupt(chip);
+	else
+		tpm_gen_interrupt(chip);
+
+	/* tpm_tis_send will either confirm the interrupt is working or it
+	 * will call disable_irq which undoes all of the above.
+	 */
+	if (!chip->vendor.irq) {
+		tpm_write_byte(chip, TPM_INT_VECTOR(chip->vendor.locality),
+			       original_int_vec);
+		return 1;
+	}
+
+	return 0;
+}
+
+/* Try to find the IRQ the TPM is using. This is for legacy x86 systems that
+ * do not have ACPI/etc. We typically expect the interrupt to be declared if
+ * present.
+ */
+static void tpm_tis_probe_irq(struct tpm_chip *chip, u32 intmask)
+{
+	u8 original_int_vec;
+	int i;
+
+	original_int_vec = tpm_read_byte(chip,
+					 TPM_INT_VECTOR(chip->vendor.locality));
+
+	if (!original_int_vec) {
+		if (IS_ENABLED(CONFIG_X86))
+			for (i = 3; i <= 15; i++)
+				if (!tpm_tis_probe_irq_single(chip, intmask, 0,
+							      i))
+					return;
+	} else if (!tpm_tis_probe_irq_single(chip, intmask, 0,
+					     original_int_vec))
+		return;
+}
+
+void tpm_tis_remove(struct tpm_chip *chip)
+{
+	if (chip->flags & TPM_CHIP_FLAG_TPM2)
+		tpm2_shutdown(chip, TPM2_SU_CLEAR);
+
+	tpm_write_dword(chip, TPM_INT_ENABLE(chip->vendor.locality),
+			~TPM_GLOBAL_INT_ENABLE &
+			tpm_read_dword(chip,
+				       TPM_INT_ENABLE(chip->vendor.locality)));
+	release_locality(chip, chip->vendor.locality, 1);
+}
+EXPORT_SYMBOL(tpm_tis_remove);
+
+int tpm_tis_init_core(struct device *dev, struct tpm_chip *chip,
+		      int irq, int irq_flags)
+{
+	u32 vendor, intfcaps, intmask;
+	int rc, probe;
+
+	/* Maximum timeouts */
+	chip->vendor.timeout_a = TIS_TIMEOUT_A_MAX;
+	chip->vendor.timeout_b = TIS_TIMEOUT_B_MAX;
+	chip->vendor.timeout_c = TIS_TIMEOUT_C_MAX;
+	chip->vendor.timeout_d = TIS_TIMEOUT_D_MAX;
+
+	if (wait_startup(chip, 0) != 0) {
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	/* Take control of the TPM's interrupt hardware and shut it off */
+	intmask = tpm_read_dword(chip, TPM_INT_ENABLE(chip->vendor.locality));
+	intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
+		   TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
+	intmask &= ~TPM_GLOBAL_INT_ENABLE;
+	tpm_write_dword(chip, TPM_INT_ENABLE(chip->vendor.locality), intmask);
+
+	if (request_locality(chip, 0) != 0) {
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	rc = tpm2_probe(chip);
+	if (rc)
+		goto out_err;
+
+	vendor = tpm_read_dword(chip, TPM_DID_VID(0));
+	chip->vendor.manufacturer_id = vendor;
+
+	dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n",
+		 (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2",
+		 vendor >> 16, tpm_read_byte(chip, TPM_RID(0)));
+
+	if (!chip->vendor.itpm) {
+		probe = probe_itpm(chip);
+		if (probe < 0) {
+			rc = -ENODEV;
+			goto out_err;
+		}
+		chip->vendor.itpm = !!probe;
+	}
+
+	if (chip->vendor.itpm)
+		dev_info(dev, "Intel iTPM workaround enabled\n");
+
+	/* Figure out the capabilities */
+	intfcaps = tpm_read_dword(chip, TPM_INTF_CAPS(chip->vendor.locality));
+	dev_dbg(dev, "TPM interface capabilities (0x%x):\n", intfcaps);
+	if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
+		dev_dbg(dev, "\tBurst Count Static\n");
+	if (intfcaps & TPM_INTF_CMD_READY_INT)
+		dev_dbg(dev, "\tCommand Ready Int Support\n");
+	if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
+		dev_dbg(dev, "\tInterrupt Edge Falling\n");
+	if (intfcaps & TPM_INTF_INT_EDGE_RISING)
+		dev_dbg(dev, "\tInterrupt Edge Rising\n");
+	if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
+		dev_dbg(dev, "\tInterrupt Level Low\n");
+	if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
+		dev_dbg(dev, "\tInterrupt Level High\n");
+	if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
+		dev_dbg(dev, "\tLocality Change Int Support\n");
+	if (intfcaps & TPM_INTF_STS_VALID_INT)
+		dev_dbg(dev, "\tSts Valid Int Support\n");
+	if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
+		dev_dbg(dev, "\tData Avail Int Support\n");
+
+	/* Very early on issue a command to the TPM in polling mode to make
+	 * sure it works. May as well use that command to set the proper
+	 *  timeouts for the driver.
+	 */
+	if (tpm_get_timeouts(chip)) {
+		dev_err(dev, "Could not get TPM timeouts and durations\n");
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	/* INTERRUPT Setup */
+	init_waitqueue_head(&chip->vendor.read_queue);
+	init_waitqueue_head(&chip->vendor.int_queue);
+	if (irq > 0) {
+		tpm_tis_probe_irq_single(chip, intmask, irq_flags, irq);
+		if (!chip->vendor.irq)
+			dev_err(&chip->dev, FW_BUG
+				"TPM interrupt not working, polling instead\n");
+	} else if (irq != -1) {
+		tpm_tis_probe_irq(chip, intmask);
+	}
+
+	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
+		rc = tpm2_do_selftest(chip);
+		if (rc == TPM2_RC_INITIALIZE) {
+			dev_warn(dev, "Firmware has not started TPM\n");
+			rc  = tpm2_startup(chip, TPM2_SU_CLEAR);
+			if (!rc)
+				rc = tpm2_do_selftest(chip);
+		}
+
+		if (rc) {
+			dev_err(dev, "TPM self test failed\n");
+			if (rc > 0)
+				rc = -ENODEV;
+			goto out_err;
+		}
+	} else {
+		if (tpm_do_selftest(chip)) {
+			dev_err(dev, "TPM self test failed\n");
+			rc = -ENODEV;
+			goto out_err;
+		}
+	}
+
+	return tpm_chip_register(chip);
+
+out_err:
+	return rc;
+}
+EXPORT_SYMBOL(tpm_tis_init_core);
+
+#ifdef CONFIG_PM_SLEEP
+static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
+{
+	u32 intmask;
+
+	/* reenable interrupts that device may have lost or
+	 * BIOS/firmware may have disabled
+	 */
+	tpm_write_byte(chip, TPM_INT_VECTOR(chip->vendor.locality), chip->vendor.irq);
+
+
+	intmask = tpm_read_dword(chip, TPM_INT_ENABLE(chip->vendor.locality));
+
+	intmask |= TPM_INTF_CMD_READY_INT
+	    | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
+	    | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE;
+
+	tpm_write_dword(chip, TPM_INT_ENABLE(chip->vendor.locality), intmask);
+}
+
+int tpm_tis_resume(struct device *dev)
+{
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	int ret;
+
+	if (chip->vendor.irq)
+		tpm_tis_reenable_interrupts(chip);
+
+	ret = tpm_pm_resume(dev);
+	if (ret)
+		return ret;
+
+	/* TPM 1.2 requires self-test on resume. This function actually returns
+	 * an error code but for unknown reason it isn't handled.
+	 */
+	if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
+		tpm_do_selftest(chip);
+
+	return 0;
+}
+EXPORT_SYMBOL(tpm_tis_resume);
+#endif
diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
new file mode 100644
index 0000000..2e2d188
--- /dev/null
+++ b/drivers/char/tpm/tpm_tis_core.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2005, 2006 IBM Corporation
+ * Copyright (C) 2014, 2015 Intel Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert-aZOuKsOsJu3MbYB6QlFGEg@public.gmane.org>
+ * Kylene Hall <kjhall-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
+ *
+ * Maintained by: <tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This device driver implements the TPM interface as defined in
+ * the TCG TPM Interface Spec version 1.2, revision 1.0.
+ *
+ * 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 the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#ifndef __TPM_TIS_CORE_H
+#define __TPM_TIS_CORE_H
+
+#include "tpm.h"
+
+enum tis_access {
+	TPM_ACCESS_VALID = 0x80,
+	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
+	TPM_ACCESS_REQUEST_PENDING = 0x04,
+	TPM_ACCESS_REQUEST_USE = 0x02,
+};
+
+enum tis_status {
+	TPM_STS_VALID = 0x80,
+	TPM_STS_COMMAND_READY = 0x40,
+	TPM_STS_GO = 0x20,
+	TPM_STS_DATA_AVAIL = 0x10,
+	TPM_STS_DATA_EXPECT = 0x08,
+	TPM_STS_RESPONSE_RETRY = 0x02,
+};
+
+enum tis_int_flags {
+	TPM_GLOBAL_INT_ENABLE = 0x80000000,
+	TPM_INTF_BURST_COUNT_STATIC = 0x100,
+	TPM_INTF_CMD_READY_INT = 0x080,
+	TPM_INTF_INT_EDGE_FALLING = 0x040,
+	TPM_INTF_INT_EDGE_RISING = 0x020,
+	TPM_INTF_INT_LEVEL_LOW = 0x010,
+	TPM_INTF_INT_LEVEL_HIGH = 0x008,
+	TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
+	TPM_INTF_STS_VALID_INT = 0x002,
+	TPM_INTF_DATA_AVAIL_INT = 0x001,
+};
+
+enum tis_defaults {
+	TIS_MEM_BASE = 0xFED40000,
+	TIS_MEM_LEN = 0x5000,
+	TIS_SHORT_TIMEOUT = 750,	/* ms */
+	TIS_LONG_TIMEOUT = 2000,	/* 2 sec */
+};
+
+/* Some timeout values are needed before it is known whether the chip is
+ * TPM 1.0 or TPM 2.0.
+ */
+#define TIS_TIMEOUT_A_MAX	max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_A)
+#define TIS_TIMEOUT_B_MAX	max(TIS_LONG_TIMEOUT, TPM2_TIMEOUT_B)
+#define TIS_TIMEOUT_C_MAX	max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_C)
+#define TIS_TIMEOUT_D_MAX	max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_D)
+
+#define	TPM_ACCESS(l)			(0x0000 | ((l) << 12))
+#define	TPM_INT_ENABLE(l)		(0x0008 | ((l) << 12))
+#define	TPM_INT_VECTOR(l)		(0x000C | ((l) << 12))
+#define	TPM_INT_STATUS(l)		(0x0010 | ((l) << 12))
+#define	TPM_INTF_CAPS(l)		(0x0014 | ((l) << 12))
+#define	TPM_STS(l)			(0x0018 | ((l) << 12))
+#define	TPM_STS3(l)			(0x001b | ((l) << 12))
+#define	TPM_DATA_FIFO(l)		(0x0024 | ((l) << 12))
+
+#define	TPM_DID_VID(l)			(0x0F00 | ((l) << 12))
+#define	TPM_RID(l)			(0x0F04 | ((l) << 12))
+
+struct tis_vendor_timeout_override {
+	u32 did_vid;
+	unsigned long timeout_us[4];
+};
+
+static const struct tis_vendor_timeout_override vendor_timeout_overrides[] = {
+	/* Atmel 3204 */
+	{ 0x32041114, { (TIS_SHORT_TIMEOUT * 1000), (TIS_LONG_TIMEOUT * 1000),
+			(TIS_SHORT_TIMEOUT * 1000), (TIS_SHORT_TIMEOUT * 1000) } },
+};
+
+u8 tpm_tis_status(struct tpm_chip *chip);
+void tpm_tis_ready(struct tpm_chip *chip);
+int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count);
+int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len);
+bool tpm_tis_update_timeouts(struct tpm_chip *chip,
+				    unsigned long *timeout_cap);
+bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status);
+int tpm_tis_resume(struct device *dev);
+void tpm_tis_remove(struct tpm_chip *chip);
+
+/* Helpers - read */
+static inline int tpm_read_bytes(struct tpm_chip *chip, u32 addr,
+				 size_t len, u8 *res)
+{
+	return chip->ops->read_bytes(chip, addr, len, 1, res);
+}
+static inline u8 tpm_read_byte(struct tpm_chip *chip, u32 addr)
+{
+	u8 res;
+
+	chip->ops->read_bytes(chip, addr, 1, sizeof(u8), &res);
+
+	return res;
+}
+
+static inline u16 tpm_read_word(struct tpm_chip *chip, u32 addr)
+{
+	u16 res;
+
+	chip->ops->read_bytes(chip, addr, 1, sizeof(u16), (u8 *)&res);
+	return res;
+}
+
+static inline u32 tpm_read_dword(struct tpm_chip *chip, u32 addr)
+{
+	u32 res;
+
+	chip->ops->read_bytes(chip, addr, 1, sizeof(u32), (u8 *)&res);
+	return res;
+}
+
+/* Helpers - write */
+static inline int tpm_write_bytes(struct tpm_chip *chip, u32 addr,
+				  size_t len, u8 *value)
+{
+	return chip->ops->write_bytes(chip, addr, 1, len, value);
+}
+
+static inline int tpm_write_byte(struct tpm_chip *chip, u32 addr, u8 value)
+{
+	u8 tmp = value;
+
+	return chip->ops->write_bytes(chip, addr, 1, sizeof(u8), &tmp);
+}
+
+static inline int tpm_write_word(struct tpm_chip *chip, u32 addr, u16 value)
+{
+	u32 tmp = value;
+
+	return chip->ops->write_bytes(chip, addr, 1, sizeof(u16), (u8 *)&tmp);
+}
+
+static inline int tpm_write_dword(struct tpm_chip *chip, u32 addr, u32 value)
+{
+	u32 tmp = value;
+
+	return chip->ops->write_bytes(chip, addr, 1, sizeof(u32), (u8 *)&tmp);
+}
+
+int tpm_tis_init_core(struct device *dev, struct tpm_chip *chip,
+		      int irq, int irq_flags);
+#endif
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 706e63e..f78e4fc 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -44,6 +44,10 @@ struct tpm_class_ops {
 	bool (*update_timeouts)(struct tpm_chip *chip,
 				unsigned long *timeout_cap);
 
+	int (*read_bytes)(struct tpm_chip *chip, u32 addr, size_t len,
+			  u8 size, u8 *dst);
+	int (*write_bytes)(struct tpm_chip *chip, u32 addr, size_t len,
+			   u8 size, u8 *src);
 };
 
 #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE)
-- 
2.5.0


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 09/12] tpm/tpm_tis: Rework interrupt management for phy compatibility
       [not found] ` <1458502483-16887-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (7 preceding siblings ...)
  2016-03-20 19:34   ` [PATCH 08/12] tpm/tpm_tis: Split tpm_tis driver into a core and TCG TIS compliant phy Christophe Ricard
@ 2016-03-20 19:34   ` Christophe Ricard
       [not found]     ` <1458502483-16887-10-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2016-03-20 19:34   ` [PATCH 10/12] tpm/tpm_tis_spi: Add support for spi phy Christophe Ricard
                     ` (5 subsequent siblings)
  14 siblings, 1 reply; 39+ messages in thread
From: Christophe Ricard @ 2016-03-20 19:34 UTC (permalink / raw)
  To: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

Rework interrupt handling in order to be compatible with every phy.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/char/tpm/tpm-interface.c | 11 ++++++++---
 drivers/char/tpm/tpm.h           |  1 +
 drivers/char/tpm/tpm_tis_core.c  | 24 +++++++++++++++++++-----
 3 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 5397b64..c06378b 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -881,7 +881,9 @@ int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
 	unsigned long stop;
 	long rc;
 	u8 status;
+	u32 cur_intrs;
 	bool canceled = false;
+	bool condition;
 
 	/* check current status */
 	status = chip->ops->status(chip);
@@ -892,14 +894,17 @@ int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
 
 	if (chip->vendor.irq) {
 again:
+		cur_intrs = chip->vendor.intrs;
 		timeout = stop - jiffies;
 		if ((long)timeout <= 0)
 			return -ETIME;
 		rc = wait_event_interruptible_timeout(*queue,
-			wait_for_tpm_stat_cond(chip, mask, check_cancel,
-					       &canceled),
+			cur_intrs != chip->vendor.intrs,
 			timeout);
-		if (rc > 0) {
+		condition = wait_for_tpm_stat_cond(chip, mask,
+						   check_cancel,
+						   &canceled);
+		if (rc > 0 && condition) {
 			if (canceled)
 				return -ECANCELED;
 			return 0;
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 3ec04f4..32c17f4 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -139,6 +139,7 @@ struct tpm_vendor_specific {
 	unsigned long base;		/* TPM base address */
 
 	int irq;
+	u32 intrs;
 
 	int region_size;
 	int have_region;
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index b9cc61f..baa9ab1 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -41,6 +41,18 @@ struct tpm_info {
 	int irq;
 };
 
+static void tpm_tis_clear_int(struct tpm_chip *chip)
+{
+	u32 interrupt;
+
+	if (chip->vendor.irq) {
+		interrupt = tpm_read_dword(chip,
+					TPM_INT_STATUS(chip->vendor.locality));
+		tpm_write_dword(chip, TPM_INT_STATUS(chip->vendor.locality),
+				interrupt);
+	}
+}
+
 /* Before we attempt to access the TPM we must see that the valid bit is set.
  * The specification says that this bit is 0 at reset and remains 0 until the
  * 'TPM has gone through its self test and initialization and has established
@@ -192,6 +204,8 @@ int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 		goto out;
 	}
 
+	tpm_tis_clear_int(chip);
+
 	/* read first 10 bytes, including tag, paramsize, and result */
 	size = recv_data(chip, buf, TPM_HEADER_SIZE);
 	if (size < TPM_HEADER_SIZE) {
@@ -313,6 +327,8 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len)
 	u32 ordinal;
 	unsigned long dur;
 
+	tpm_tis_clear_int(chip);
+
 	rc = tpm_tis_send_data(chip, buf, len);
 	if (rc < 0)
 		return rc;
@@ -455,6 +471,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
 		return IRQ_NONE;
 
 	chip->vendor.irq_tested = true;
+	chip->vendor.intrs++;
 	if (interrupt & TPM_INTF_DATA_AVAIL_INT)
 		wake_up_interruptible(&chip->vendor.read_queue);
 	if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
@@ -466,9 +483,6 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
 	     TPM_INTF_CMD_READY_INT))
 		wake_up_interruptible(&chip->vendor.int_queue);
 
-	/* Clear interrupts handled with TPM_EOI */
-	tpm_write_dword(chip, TPM_INT_STATUS(chip->vendor.locality), interrupt);
-	tpm_read_dword(chip, TPM_INT_STATUS(chip->vendor.locality));
 	return IRQ_HANDLED;
 }
 
@@ -481,8 +495,8 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
 {
 	u8 original_int_vec;
 
-	if (devm_request_irq(&chip->dev, irq, tis_int_handler, flags,
-			     dev_name(&chip->dev), chip) != 0) {
+	if (devm_request_threaded_irq(&chip->dev, irq, NULL, tis_int_handler, flags,
+				      dev_name(&chip->dev), chip) != 0) {
 		dev_info(&chip->dev, "Unable to request irq: %d for probe\n",
 			 irq);
 		return -1;
-- 
2.5.0


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 10/12] tpm/tpm_tis_spi: Add support for spi phy
       [not found] ` <1458502483-16887-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (8 preceding siblings ...)
  2016-03-20 19:34   ` [PATCH 09/12] tpm/tpm_tis: Rework interrupt management for phy compatibility Christophe Ricard
@ 2016-03-20 19:34   ` Christophe Ricard
  2016-03-20 19:34   ` [PATCH 11/12] tpm: Add check_data handle to tpm_class_ops in order to check data integrity Christophe Ricard
                     ` (4 subsequent siblings)
  14 siblings, 0 replies; 39+ messages in thread
From: Christophe Ricard @ 2016-03-20 19:34 UTC (permalink / raw)
  To: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, Peter Huewe,
	benoit.houyere-qxv4g6HH51o

A spi protocol standardized by the TCG is now supported by most of TPM
vendors.

It supports wait cycle on MISO line.

Signed-off-by: Peter Huewe <peter.huewe-d0qZbvYSIPpWk0Htik3J/w@public.gmane.org>
Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 .../bindings/security/tpm/tpm_tis_spi.txt          |  28 +++
 drivers/char/tpm/Kconfig                           |  12 +-
 drivers/char/tpm/Makefile                          |   1 +
 drivers/char/tpm/tpm_tis_spi.c                     | 279 +++++++++++++++++++++
 4 files changed, 319 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/security/tpm/tpm_tis_spi.txt
 create mode 100644 drivers/char/tpm/tpm_tis_spi.c

diff --git a/Documentation/devicetree/bindings/security/tpm/tpm_tis_spi.txt b/Documentation/devicetree/bindings/security/tpm/tpm_tis_spi.txt
new file mode 100644
index 0000000..e0464b0
--- /dev/null
+++ b/Documentation/devicetree/bindings/security/tpm/tpm_tis_spi.txt
@@ -0,0 +1,28 @@
+Required properties:
+- compatible: Should be "st,st33htpm-spi" or "infineon,slb9670" or "tcg,tpm_tis-spi"
+- spi-max-frequency: Maximum SPI frequency (depends on TPMs).
+
+Optional TPM_TIS SPI Properties:
+- interrupt-parent: phandle for the interrupt gpio controller
+- interrupts: GPIO interrupt to which the chip is connected
+
+Optional SoC Specific Properties:
+- pinctrl-names: Contains only one value - "default".
+- pintctrl-0: Specifies the pin control groups used for this controller.
+
+Example (for ARM-based BeagleBoard xM with TPM_TIS on SPI4):
+
+&mcspi4 {
+
+        status = "okay";
+
+        tpm_tis@0 {
+
+                compatible = "tcg,tpm_tis-spi";
+
+                spi-max-frequency = <10000000>;
+
+                interrupt-parent = <&gpio5>;
+                interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
+        };
+};
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 3b84a8b..6fbe7468 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -26,7 +26,6 @@ if TCG_TPM
 
 config TCG_TIS
 	tristate "TPM Interface Specification 1.2 Interface / TPM 2.0 FIFO Interface"
-	depends on X86
 	---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
@@ -64,6 +63,17 @@ config TCG_TIS_I2C_NUVOTON
 	  To compile this driver as a module, choose M here; the module
 	  will be called tpm_i2c_nuvoton.
 
+config TCG_TIS_SPI
+	tristate "TPM Interface Specification 1.3 Interface / TPM 2.0 FIFO Interface - (SPI)"
+	depends on SPI
+	---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_spi_tis.
+
 config TCG_NSC
 	tristate "National Semiconductor TPM Interface"
 	depends on X86
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index c6a4cea..69508ef 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_TCG_TIS) += tpm_tis.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
+obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi.o
 obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
 obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
 obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c
new file mode 100644
index 0000000..3cdc3a8
--- /dev/null
+++ b/drivers/char/tpm/tpm_tis_spi.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2015 Infineon Technologies AG
+ * Copyright (C) 2016 STMicroelectronics SAS
+ *
+ * Authors:
+ * Peter Huewe <peter.huewe-d0qZbvYSIPpWk0Htik3J/w@public.gmane.org>
+ * Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
+ *
+ * Maintained by: <tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This device driver implements the TPM interface as defined in
+ * the TCG TPM Interface Spec version 1.3, revision 27 via _raw/native
+ * SPI access_.
+ *
+ * It is based on the original tpm_tis device driver from Leendert van
+ * Dorn and Kyleen Hall and Jarko Sakkinnen.
+ *
+ * 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 the Free Software Foundation, version 2 of the
+ * License.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/acpi.h>
+#include <linux/freezer.h>
+
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/tpm.h>
+#include "tpm.h"
+#include "tpm_tis_core.h"
+
+#define MAX_SPI_FRAMESIZE 64
+
+struct tpm_tis_spi_phy {
+	struct spi_device *spi_device;
+	struct mutex phy_lock;
+
+	u8 tx_buf[MAX_SPI_FRAMESIZE + 4];
+	u8 rx_buf[MAX_SPI_FRAMESIZE + 4];
+};
+
+static int tpm_tis_spi_read_bytes(struct tpm_chip *chip, u32 addr,
+				  size_t len, u8 size, u8 *result)
+{
+	int ret;
+	struct tpm_tis_spi_phy *phy = tpm_get_vendordata(chip);
+	struct spi_message m;
+	struct spi_transfer spi_xfer = {
+		.tx_buf = phy->tx_buf,
+		.rx_buf = phy->rx_buf,
+		.len = 4,
+	};
+
+	if (len > MAX_SPI_FRAMESIZE)
+		return -ENOMEM;
+
+	phy->tx_buf[0] = 0x80 | (len * size - 1);
+	phy->tx_buf[1] = 0xd4;
+	phy->tx_buf[2] = (addr >> 8)  & 0xFF;
+	phy->tx_buf[3] = addr	      & 0xFF;
+
+	spi_xfer.cs_change = 1;
+	spi_message_init(&m);
+	spi_message_add_tail(&spi_xfer, &m);
+
+	mutex_lock(&phy->phy_lock);
+	spi_bus_lock(phy->spi_device->master);
+	ret = spi_sync_locked(phy->spi_device, &m);
+	if (ret < 0)
+		goto exit;
+
+	memset(phy->tx_buf, 0, len * size);
+
+	/* According to TCG PTP specification, if there is no TPM present at
+	 * all, then the design has a weak pull-up on MISO. If a TPM is not
+	 * present, a pull-up on MISO means that the SB controller sees a 1,
+	 * and will latch in 0xFF on the read.
+	 */
+	for ( ; (phy->rx_buf[0] & 0x01) == 0 ; ) {
+		spi_xfer.len = 1;
+		spi_message_init(&m);
+		spi_message_add_tail(&spi_xfer, &m);
+		ret = spi_sync_locked(phy->spi_device, &m);
+		if (ret < 0)
+			goto exit;
+	}
+
+	spi_xfer.cs_change = 0;
+	spi_xfer.len = len * size;
+	spi_xfer.rx_buf = result;
+
+	spi_message_init(&m);
+	spi_message_add_tail(&spi_xfer, &m);
+	ret = spi_sync_locked(phy->spi_device, &m);
+
+exit:
+	spi_bus_unlock(phy->spi_device->master);
+	mutex_unlock(&phy->phy_lock);
+	return ret;
+}
+
+static int tpm_tis_spi_write_bytes(struct tpm_chip *chip, u32 addr,
+				   size_t len, u8 size, u8 *value)
+{
+	int ret;
+	struct tpm_tis_spi_phy *phy = tpm_get_vendordata(chip);
+	struct spi_message m;
+	struct spi_transfer spi_xfer = {
+		.tx_buf = phy->tx_buf,
+		.rx_buf = phy->rx_buf,
+		.len = 4,
+	};
+
+	if (len > MAX_SPI_FRAMESIZE)
+		return -ENOMEM;
+
+	phy->tx_buf[0] = len * size - 1;
+	phy->tx_buf[1] = 0xd4;
+	phy->tx_buf[2] = (addr >> 8)  & 0xFF;
+	phy->tx_buf[3] = addr         & 0xFF;
+
+	spi_xfer.cs_change = 1;
+	spi_message_init(&m);
+	spi_message_add_tail(&spi_xfer, &m);
+
+	mutex_lock(&phy->phy_lock);
+	spi_bus_lock(phy->spi_device->master);
+	ret = spi_sync_locked(phy->spi_device, &m);
+	if (ret < 0)
+		goto exit;
+
+	memset(phy->tx_buf, 0, len * size);
+
+	/* According to TCG PTP specification, if there is no TPM present at
+	 * all, then the design has a weak pull-up on MISO. If a TPM is not
+	 * present, a pull-up on MISO means that the SB controller sees a 1,
+	 * and will latch in 0xFF on the read.
+	 */
+	for ( ; (phy->rx_buf[0] & 0x01) == 0 ; ) {
+		spi_xfer.len = 1;
+		spi_message_init(&m);
+		spi_message_add_tail(&spi_xfer, &m);
+		ret = spi_sync_locked(phy->spi_device, &m);
+		if (ret < 0)
+			goto exit;
+	}
+
+	spi_xfer.len = len * size;
+	spi_xfer.tx_buf = value;
+	spi_xfer.cs_change = 0;
+	spi_xfer.tx_buf = value;
+	spi_message_init(&m);
+	spi_message_add_tail(&spi_xfer, &m);
+	ret = spi_sync_locked(phy->spi_device, &m);
+
+exit:
+	spi_bus_unlock(phy->spi_device->master);
+	mutex_unlock(&phy->phy_lock);
+	return ret;
+}
+
+static const struct tpm_class_ops tpm_tis = {
+	.status = tpm_tis_status,
+	.recv = tpm_tis_recv,
+	.send = tpm_tis_send,
+	.cancel = tpm_tis_ready,
+	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_canceled = tpm_tis_req_canceled,
+	.read_bytes = tpm_tis_spi_read_bytes,
+	.write_bytes = tpm_tis_spi_write_bytes,
+};
+
+static SIMPLE_DEV_PM_OPS(tpm_tis_spi_pm, tpm_pm_suspend, tpm_tis_resume);
+
+static int tpm_tis_spi_probe(struct spi_device *dev)
+{
+	struct tpm_tis_spi_phy *phy;
+	struct tpm_chip *chip;
+	unsigned int irq_polarity = IRQ_TYPE_NONE;
+	int ret, irq = -1;
+
+	/* Check SPI platform functionnalities */
+	if (!dev) {
+		pr_err("%s: dev is NULL. Device is not accessible.\n",
+				__func__);
+		return -ENODEV;
+	}
+
+	phy = devm_kzalloc(&dev->dev, sizeof(struct tpm_tis_spi_phy),
+			     GFP_KERNEL);
+	if (!phy)
+		return -ENOMEM;
+
+	chip = tpmm_chip_alloc(&dev->dev, &tpm_tis);
+	if (IS_ERR(chip))
+		return PTR_ERR(chip);
+
+	phy->spi_device = dev;
+	mutex_init(&phy->phy_lock);
+	tpm_set_vendordata(chip, phy);
+
+	if (dev->irq > 0) {
+		irq = dev->irq;
+		irq_polarity = irq_get_trigger_type(irq);
+		if (irq_polarity > 0)
+			irq_polarity |= IRQF_ONESHOT;
+		else
+			irq = -1;
+	}
+
+	ret = tpm_tis_init_core(&dev->dev, chip, irq, irq_polarity);
+	if (ret < 0)
+		goto out_err;
+
+	return ret;
+
+out_err:
+	tpm_tis_remove(chip);
+	return ret;
+}
+
+static int tpm_tis_spi_remove(struct spi_device *dev)
+{
+	struct tpm_chip *chip = spi_get_drvdata(dev);
+
+	tpm_chip_unregister(chip);
+	return 0;
+}
+
+static const struct spi_device_id tpm_tis_spi_id[] = {
+	{"tpm_tis_spi", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(spi, tpm_tis_spi_id);
+
+static const struct of_device_id of_tis_spi_match[] = {
+	{ .compatible = "st,st33htpm-spi", },
+	{ .compatible = "infineon,slb9670", },
+	{ .compatible = "tcg,tpm_tis-spi", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, of_tis_spi_match);
+
+static const struct acpi_device_id acpi_tis_spi_match[] = {
+	{"SMO0768", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(acpi, acpi_tis_spi_match);
+
+static struct spi_driver tpm_tis_spi_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "tpm_tis_spi",
+		.pm = &tpm_tis_spi_pm,
+		.of_match_table = of_match_ptr(of_tis_spi_match),
+		.acpi_match_table = ACPI_PTR(acpi_tis_spi_match),
+	},
+	.probe = tpm_tis_spi_probe,
+	.remove = tpm_tis_spi_remove,
+	.id_table = tpm_tis_spi_id,
+};
+module_spi_driver(tpm_tis_spi_driver);
+
+MODULE_DESCRIPTION("TPM Driver for native SPI access");
+MODULE_LICENSE("GPL");
-- 
2.5.0


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 11/12] tpm: Add check_data handle to tpm_class_ops in order to check data integrity
       [not found] ` <1458502483-16887-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (9 preceding siblings ...)
  2016-03-20 19:34   ` [PATCH 10/12] tpm/tpm_tis_spi: Add support for spi phy Christophe Ricard
@ 2016-03-20 19:34   ` Christophe Ricard
       [not found]     ` <1458502483-16887-12-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2016-03-20 19:34   ` [PATCH 12/12] tpm/tpm_tis_i2c: Add support for i2c phy Christophe Ricard
                     ` (3 subsequent siblings)
  14 siblings, 1 reply; 39+ messages in thread
From: Christophe Ricard @ 2016-03-20 19:34 UTC (permalink / raw)
  To: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

For example, in order to compute crc over the data sent in lower layer
(i2c for instance), provide a specific handle.

The current principles:
- When sending command:
1) Host writes TPM_STS.commandReady
2) Host writes command
3) Host checks TPM received data correctly
4) if not go to step 1

- When receiving data:
1) Host check TPM_STS.dataAvail is set
2) Host get data
3) Host check received data are correct.
4) if not Host write TPM_STS.responseRetry and go to step 1.

Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
---
 drivers/char/tpm/tpm_tis_core.c | 81 ++++++++++++++++++++++++++---------------
 include/linux/tpm.h             |  1 +
 2 files changed, 52 insertions(+), 30 deletions(-)

diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index baa9ab1..9efb3ac 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -126,6 +126,14 @@ again:
 	return -1;
 }
 
+static bool tpm_tis_check_data(struct tpm_chip *chip, u8 *buf, size_t len)
+{
+	if (chip->ops->check_data)
+		return chip->ops->check_data(chip, buf, len);
+
+	return true;
+}
+
 u8 tpm_tis_status(struct tpm_chip *chip)
 {
 	return tpm_read_byte(chip, TPM_STS(chip->vendor.locality));
@@ -197,7 +205,8 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
 int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 {
 	int size = 0;
-	int expected, status;
+	int expected, status, i;
+	bool check_data = false;
 
 	if (count < TPM_HEADER_SIZE) {
 		size = -EIO;
@@ -206,34 +215,41 @@ int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 
 	tpm_tis_clear_int(chip);
 
-	/* read first 10 bytes, including tag, paramsize, and result */
-	size = recv_data(chip, buf, TPM_HEADER_SIZE);
-	if (size < TPM_HEADER_SIZE) {
-		dev_err(&chip->dev, "Unable to read header\n");
-		goto out;
-	}
+	for (i = 0; i < TPM_RETRY && !check_data; i++) {
+		/* read first 10 bytes, including tag, paramsize, and result */
+		size = recv_data(chip, buf, TPM_HEADER_SIZE);
+		if (size < TPM_HEADER_SIZE) {
+			dev_err(&chip->dev, "Unable to read header\n");
+			goto out;
+		}
 
-	expected = be32_to_cpu(*(__be32 *) (buf + 2));
-	if (expected > count) {
-		size = -EIO;
-		goto out;
-	}
+		expected = be32_to_cpu(*(__be32 *) (buf + 2));
+		if (expected > count) {
+			size = -EIO;
+			goto out;
+		}
 
-	size += recv_data(chip, &buf[TPM_HEADER_SIZE],
-			  expected - TPM_HEADER_SIZE);
-	if (size < expected) {
-		dev_err(&chip->dev, "Unable to read remainder of result\n");
-		size = -ETIME;
-		goto out;
-	}
+		size += recv_data(chip, &buf[TPM_HEADER_SIZE],
+				  expected - TPM_HEADER_SIZE);
+		if (size < expected) {
+			dev_err(&chip->dev, "Unable to read remainder of result\n");
+			size = -ETIME;
+			goto out;
+		}
 
-	wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
-			  &chip->vendor.int_queue, false);
-	status = tpm_tis_status(chip);
-	if (status & TPM_STS_DATA_AVAIL) {	/* retry? */
-		dev_err(&chip->dev, "Error left over data\n");
-		size = -EIO;
-		goto out;
+		wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+				  &chip->vendor.int_queue, false);
+		status = tpm_tis_status(chip);
+		if (status & TPM_STS_DATA_AVAIL) {	/* retry? */
+			dev_err(&chip->dev, "Error left over data\n");
+			size = -EIO;
+			goto out;
+		}
+
+		check_data = tpm_tis_check_data(chip, buf, size);
+		if (!check_data)
+			tpm_write_byte(chip, TPM_STS(chip->vendor.locality),
+				       TPM_STS_RESPONSE_RETRY);
 	}
 
 out:
@@ -323,15 +339,20 @@ static void disable_interrupts(struct tpm_chip *chip)
  */
 static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len)
 {
-	int rc;
+	int rc, i;
 	u32 ordinal;
 	unsigned long dur;
+	bool data_valid = false;
 
 	tpm_tis_clear_int(chip);
 
-	rc = tpm_tis_send_data(chip, buf, len);
-	if (rc < 0)
-		return rc;
+	for (i = 0; i < TPM_RETRY && !data_valid; i++) {
+		rc = tpm_tis_send_data(chip, buf, len);
+		if (rc < 0)
+			return rc;
+
+		data_valid = tpm_tis_check_data(chip, buf, len);
+	}
 
 	/* go and do it */
 	tpm_write_byte(chip, TPM_STS(chip->vendor.locality), TPM_STS_GO);
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index f78e4fc..8e871dc 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -43,6 +43,7 @@ struct tpm_class_ops {
 	u8 (*status) (struct tpm_chip *chip);
 	bool (*update_timeouts)(struct tpm_chip *chip,
 				unsigned long *timeout_cap);
+	bool (*check_data)(struct tpm_chip *chip, u8 *buf, size_t len);
 
 	int (*read_bytes)(struct tpm_chip *chip, u32 addr, size_t len,
 			  u8 size, u8 *dst);
-- 
2.5.0


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* [PATCH 12/12] tpm/tpm_tis_i2c: Add support for i2c phy
       [not found] ` <1458502483-16887-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (10 preceding siblings ...)
  2016-03-20 19:34   ` [PATCH 11/12] tpm: Add check_data handle to tpm_class_ops in order to check data integrity Christophe Ricard
@ 2016-03-20 19:34   ` Christophe Ricard
  2016-03-20 21:59   ` [PATCH 00/12] Few minnor fixes, rework of tpm_tis to support tcg spi and i2c Peter Huewe
                     ` (2 subsequent siblings)
  14 siblings, 0 replies; 39+ messages in thread
From: Christophe Ricard @ 2016-03-20 19:34 UTC (permalink / raw)
  To: jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

A i2c protocol standardized by the TCG is now supported by most of TPM
vendors.

Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
---
 .../bindings/security/tpm/tpm_tis_i2c.txt          |  30 ++
 drivers/char/tpm/Kconfig                           |  14 +-
 drivers/char/tpm/Makefile                          |   1 +
 drivers/char/tpm/tpm_tis_i2c.c                     | 499 +++++++++++++++++++++
 4 files changed, 543 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/security/tpm/tpm_tis_i2c.txt
 create mode 100644 drivers/char/tpm/tpm_tis_i2c.c

diff --git a/Documentation/devicetree/bindings/security/tpm/tpm_tis_i2c.txt b/Documentation/devicetree/bindings/security/tpm/tpm_tis_i2c.txt
new file mode 100644
index 0000000..a09f922
--- /dev/null
+++ b/Documentation/devicetree/bindings/security/tpm/tpm_tis_i2c.txt
@@ -0,0 +1,30 @@
+Required properties:
+- compatible: Should be "st,st33htpm-i2c" or "tcg,tpm_tis-i2c"
+- clock-frequency: I²C work frequency.
+- reg: address on the bus
+
+Optional TPM_TIS Properties:
+- interrupt-parent: phandle for the interrupt gpio controller
+- interrupts: GPIO interrupt to which the chip is connected
+
+Optional SoC Specific Properties:
+- pinctrl-names: Contains only one value - "default".
+- pintctrl-0: Specifies the pin control groups used for this controller.
+
+Example (for ARM-based BeagleBoard xM with TPM_TIS on I2C2):
+
+&i2c2 {
+
+        status = "okay";
+
+        tpm_tis: tpm_tis@17 {
+
+                compatible = "st,tpm_tis-i2c";
+
+                reg = <0x17>;
+                clock-frequency = <400000>;
+
+                interrupt-parent = <&gpio5>;
+                interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
+        };
+};
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 6fbe7468..56afc2f 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -72,7 +72,19 @@ config TCG_TIS_SPI
 	  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_spi_tis.
+	  the module will be called tpm_tis_spi.
+
+config TCG_TIS_I2C
+	tristate "TPM Interface Specification 1.3 Interface / TPM 2.0 FIFO Interface - (I2C)"
+	depends on I2C
+	depends on CRC_CCITT
+	---help---
+	  If you have a TPM security chip which is connected to a regular,
+	  non-tcg I2C 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_i2c.
 
 config TCG_NSC
 	tristate "National Semiconductor TPM Interface"
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 69508ef..eec3793 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -17,6 +17,7 @@ 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
 obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi.o
+obj-$(CONFIG_TCG_TIS_I2C) += tpm_tis_i2c.o
 obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
 obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
 obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
diff --git a/drivers/char/tpm/tpm_tis_i2c.c b/drivers/char/tpm/tpm_tis_i2c.c
new file mode 100644
index 0000000..0591d13
--- /dev/null
+++ b/drivers/char/tpm/tpm_tis_i2c.c
@@ -0,0 +1,499 @@
+/*
+ * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
+ * Copyright (C) 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/acpi.h>
+#include <linux/freezer.h>
+#include <linux/crc-ccitt.h>
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/tpm.h>
+#include "tpm.h"
+#include "tpm_tis_core.h"
+
+#define TPM_LOC_SEL			0x04
+#define TPM_I2C_INTERFACE_CAPABILITY	0x30
+#define TPM_I2C_DEVICE_ADDRESS		0x38
+#define TPM_DATA_CSUM_ENABLE		0x40
+#define TPM_DATA_CSUM			0x44
+#define TPM_I2C_DID_VID			0x48
+#define TPM_I2C_RID			0x4C
+
+#define TPM_I2C_DEFAULT_GUARD_TIME	0xFA
+
+enum tpm_tis_i2c_operation {
+	TPM_I2C_NONE,
+	TPM_I2C_RECV,
+	TPM_I2C_SEND,
+};
+
+#define TPM_I2C_DEVADRCHANGE(x)		((0x18000000 & x) >> 27)
+#define TPM_I2C_READ_READ(x)		((0x00100000 & x) >> 20)
+#define TPM_I2C_READ_WRITE(x)		((0x00080000 & x) >> 19)
+#define TPM_I2C_WRITE_READ(x)		((0x00040000 & x) >> 18)
+#define TPM_I2C_WRITE_WRITE(x)		((0x00020000 & x) >> 17)
+#define TPM_I2C_GUARD_TIME(x)		((0x0001FE00 & x) >> 9)
+
+struct tpm_tis_i2c_phy {
+	struct i2c_client *client;
+	u8 buf[TPM_BUFSIZE + 1];
+	u8 last_i2c_ops;
+
+	struct timer_list guard_timer;
+	struct mutex phy_lock;
+
+	bool data_csum;
+	bool devadrchange;
+	bool read_read;
+	bool read_write;
+	bool write_read;
+	bool write_write;
+	u8 guard_time;
+};
+
+static int tpm_tis_i2c_ptp_register_mapper(u32 addr, u8 *i2c_reg)
+{
+	*i2c_reg = (u8)(0x000000ff & addr);
+
+	switch (addr) {
+	case TPM_ACCESS(0):
+		*i2c_reg = TPM_LOC_SEL;
+		break;
+	case TPM_LOC_SEL:
+		*i2c_reg = TPM_ACCESS(0);
+		break;
+	case TPM_DID_VID(0):
+		*i2c_reg = TPM_I2C_DID_VID;
+		break;
+	case TPM_RID(0):
+		*i2c_reg = TPM_I2C_RID;
+		break;
+	case TPM_INT_VECTOR(0):
+		return -1;
+	}
+
+	return 0;
+}
+
+static void tpm_tis_i2c_guard_time_timeout(unsigned long data)
+{
+	struct tpm_tis_i2c_phy *phy = (struct tpm_tis_i2c_phy *)data;
+
+	pr_debug("\n");
+
+	/* GUARD_TIME expired */
+	phy->last_i2c_ops = TPM_I2C_NONE;
+}
+
+static void tpm_tis_i2c_sleep_guard_time(struct tpm_tis_i2c_phy *phy,
+					 u8 i2c_operation)
+{
+	del_timer_sync(&phy->guard_timer);
+	switch (i2c_operation) {
+	case TPM_I2C_RECV:
+		switch (phy->last_i2c_ops) {
+		case TPM_I2C_RECV:
+		if (phy->read_read)
+			udelay(phy->guard_time);
+		break;
+		case TPM_I2C_SEND:
+		if (phy->write_read)
+			udelay(phy->guard_time);
+		break;
+		}
+	break;
+	case TPM_I2C_SEND:
+		switch (phy->last_i2c_ops) {
+		case TPM_I2C_RECV:
+		if (phy->read_write)
+			udelay(phy->guard_time);
+		break;
+		case TPM_I2C_SEND:
+		if (phy->write_write)
+			udelay(phy->guard_time);
+		break;
+		}
+	break;
+	}
+	phy->last_i2c_ops = i2c_operation;
+}
+
+static int tpm_tis_i2c_read_bytes(struct tpm_chip *chip, u32 addr, size_t len,
+				  u8 size, u8 *result)
+{
+	struct tpm_tis_i2c_phy *phy = tpm_get_vendordata(chip);
+	int i, ret;
+	u8 i2c_reg;
+
+	mutex_lock(&phy->phy_lock);
+	ret = tpm_tis_i2c_ptp_register_mapper(addr, &i2c_reg);
+	if (ret < 0) {
+		/* If we don't have any register equivalence in i2c
+		 * ignore the sequence.
+		 */
+		ret = len;
+		goto exit;
+	}
+	ret = -1;
+
+	for (i = 0; i < TPM_RETRY && ret < 0; i++) {
+		tpm_tis_i2c_sleep_guard_time(phy, TPM_I2C_SEND);
+		ret = i2c_master_send(phy->client, &i2c_reg, 1);
+		mod_timer(&phy->guard_timer, phy->guard_time);
+	}
+
+	if (ret < 0)
+		goto exit;
+
+	ret = -1;
+	for (i = 0; i < TPM_RETRY && ret < 0; i++) {
+		tpm_tis_i2c_sleep_guard_time(phy, TPM_I2C_RECV);
+		ret = i2c_master_recv(phy->client, result, len * size);
+		mod_timer(&phy->guard_timer, phy->guard_time);
+	}
+
+exit:
+	mutex_unlock(&phy->phy_lock);
+	return ret;
+}
+
+static int tpm_tis_i2c_write_bytes(struct tpm_chip *chip, u32 addr, size_t len,
+				   u8 size, u8 *value)
+{
+	struct tpm_tis_i2c_phy *phy = tpm_get_vendordata(chip);
+	int i, ret;
+	u8 i2c_reg;
+
+	mutex_lock(&phy->phy_lock);
+	ret = tpm_tis_i2c_ptp_register_mapper(addr, &i2c_reg);
+	if (ret < 0) {
+		/* If we don't have any register equivalence in i2c
+		 * ignore the sequence.
+		 */
+		ret = len * size;
+		goto exit;
+	}
+
+	ret = -1;
+	phy->buf[0] = i2c_reg;
+	memcpy(phy->buf + 1, value, len * size);
+
+	for (i = 0; i < TPM_RETRY && (ret < 0 || ret < len + 1); i++) {
+		tpm_tis_i2c_sleep_guard_time(phy, TPM_I2C_SEND);
+		ret = i2c_master_send(phy->client, phy->buf, len * size + 1);
+		mod_timer(&phy->guard_timer, phy->guard_time);
+	}
+
+exit:
+	mutex_unlock(&phy->phy_lock);
+	return ret;
+}
+
+static bool tpm_tis_i2c_check_data(struct tpm_chip *chip, u8 *buf, size_t len)
+{
+	struct tpm_tis_i2c_phy *phy = tpm_get_vendordata(chip);
+	u16 crc, crc_tpm;
+
+	if (phy->data_csum) {
+		crc = crc_ccitt(0x0000, buf, len);
+
+		crc_tpm = tpm_read_word(chip, TPM_DATA_CSUM);
+		crc_tpm = be16_to_cpu(crc_tpm);
+
+		return crc == crc_tpm;
+	}
+	return true;
+}
+
+static const struct tpm_class_ops tpm_tis = {
+	.status = tpm_tis_status,
+	.recv = tpm_tis_recv,
+	.send = tpm_tis_send,
+	.cancel = tpm_tis_ready,
+	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_canceled = tpm_tis_req_canceled,
+	.read_bytes = tpm_tis_i2c_read_bytes,
+	.write_bytes = tpm_tis_i2c_write_bytes,
+	.check_data = tpm_tis_i2c_check_data,
+};
+
+static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_pm, tpm_pm_suspend, tpm_tis_resume);
+
+static ssize_t i2c_addr_show(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+
+	if (client)
+		return sprintf(buf, "0x%.2x\n", client->addr);
+
+	return 0;
+}
+
+static ssize_t i2c_addr_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	struct tpm_tis_i2c_phy *phy;
+	long new_addr;
+	u16 cur_addr;
+	int ret = 0;
+
+	if (!chip)
+		goto exit;
+
+	phy = tpm_get_vendordata(chip);
+	if (!phy || !phy->client || !phy->devadrchange)
+		goto exit;
+
+	/* Base string automatically detected */
+	ret = kstrtol(buf, 0, &new_addr);
+	if (ret < 0)
+		goto exit;
+
+	ret = tpm_write_word(chip, TPM_I2C_DEVICE_ADDRESS, new_addr);
+	if (ret < 0)
+		goto exit;
+
+	cur_addr = tpm_read_word(chip, TPM_I2C_DEVICE_ADDRESS);
+	if (cur_addr == new_addr) {
+		phy->client->addr = new_addr & 0x00ff;
+		return count;
+	}
+
+	return -EINVAL;
+exit:
+	return ret;
+}
+static DEVICE_ATTR_RW(i2c_addr);
+
+static ssize_t csum_state_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	struct tpm_tis_i2c_phy *phy;
+
+	if (!chip)
+		goto exit;
+
+	phy = tpm_get_vendordata(chip);
+	if (!phy || !phy->client)
+		goto exit;
+
+	return sprintf(buf, "%x\n", phy->data_csum);
+exit:
+	return 0;
+}
+
+static ssize_t csum_state_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	struct tpm_tis_i2c_phy *phy;
+	long new_state;
+	u8 cur_state;
+	int ret = 0;
+
+	if (!chip)
+		goto exit;
+
+	phy = tpm_get_vendordata(chip);
+	if (!phy || !phy->client)
+		goto exit;
+
+	ret = kstrtol(buf, 2, &new_state);
+	if (ret < 0)
+		goto exit;
+
+	ret = tpm_write_byte(chip, TPM_DATA_CSUM_ENABLE, new_state);
+	if (ret < 0)
+		goto exit;
+
+	cur_state = tpm_read_byte(chip, TPM_DATA_CSUM_ENABLE);
+	if (new_state == cur_state) {
+		phy->data_csum = cur_state;
+		return count;
+	}
+
+	return -EINVAL;
+exit:
+	return ret;
+}
+static DEVICE_ATTR_RW(csum_state);
+
+static struct attribute *tpm_tis_i2c_attrs[] = {
+	&dev_attr_i2c_addr.attr,
+	&dev_attr_csum_state.attr,
+	NULL,
+};
+
+static struct attribute_group tpm_tis_i2c_attr_group = {
+	.attrs = tpm_tis_i2c_attrs,
+};
+
+static int tpm_tis_i2c_probe(struct i2c_client *client,
+			     const struct i2c_device_id *id)
+{
+	struct tpm_tis_i2c_phy *phy;
+	struct tpm_chip *chip;
+	unsigned int irq_polarity = IRQ_TYPE_NONE;
+	int ret, irq = -1;
+	u32 tmp;
+
+	if (!client) {
+		pr_err("%s: i2c client is NULL. Device not accessible.\n",
+				__func__);
+		return -ENODEV;
+	}
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_info(&client->dev, "client not i2c capable\n");
+		return -ENODEV;
+	}
+
+	phy = devm_kzalloc(&client->dev, sizeof(struct tpm_tis_i2c_phy),
+			   GFP_KERNEL);
+	if (!phy)
+		return -ENOMEM;
+
+	chip = tpmm_chip_alloc(&client->dev, &tpm_tis);
+	if (IS_ERR(chip))
+		return PTR_ERR(chip);
+
+	phy->client = client;
+	mutex_init(&phy->phy_lock);
+	tpm_set_vendordata(chip, phy);
+	i2c_set_clientdata(client, chip);
+
+	phy->guard_time = TPM_I2C_DEFAULT_GUARD_TIME;
+	phy->read_read = true;
+	phy->read_write = true;
+	phy->write_read = true;
+	phy->write_write = true;
+
+	/* initialize timer */
+	init_timer(&phy->guard_timer);
+	phy->guard_timer.data = (unsigned long)phy;
+	phy->guard_timer.function = tpm_tis_i2c_guard_time_timeout;
+
+	ret = tpm_write_byte(chip, TPM_LOC_SEL, 0);
+	if (ret < 0)
+		goto out_err;
+
+	phy->data_csum = tpm_read_byte(chip, TPM_DATA_CSUM_ENABLE);
+
+	if (client->irq > 0) {
+		irq = client->irq;
+		irq_polarity = irq_get_trigger_type(irq);
+		if (irq_polarity > 0)
+			irq_polarity |= IRQF_ONESHOT;
+		else
+			irq = -1;
+	}
+
+	ret = tpm_tis_init_core(&client->dev, chip, irq, irq_polarity);
+	if (ret < 0)
+		goto out_err;
+
+	tmp = tpm_read_dword(chip, TPM_I2C_INTERFACE_CAPABILITY);
+
+	tmp = be32_to_cpu((__force __be32)tmp);
+
+	phy->devadrchange = TPM_I2C_DEVADRCHANGE(tmp);
+	phy->read_read = TPM_I2C_READ_READ(tmp);
+	phy->read_write = TPM_I2C_READ_WRITE(tmp);
+	phy->write_read = TPM_I2C_WRITE_READ(tmp);
+	phy->write_write = TPM_I2C_WRITE_WRITE(tmp);
+	phy->guard_time = TPM_I2C_GUARD_TIME(tmp);
+
+	ret = sysfs_create_group(&client->dev.kobj, &tpm_tis_i2c_attr_group);
+	if (ret < 0) {
+		dev_err(&chip->dev,
+			"failed to create sysfs attributes, %d\n", ret);
+		goto deinit_err;
+	}
+
+	return ret;
+
+deinit_err:
+	tpm_chip_unregister(chip);
+out_err:
+	tpm_tis_remove(chip);
+	return ret;
+}
+
+static int tpm_tis_i2c_remove(struct i2c_client *client)
+{
+	struct tpm_chip *chip = i2c_get_clientdata(client);
+
+	tpm_chip_unregister(chip);
+	tpm_tis_remove(chip);
+	sysfs_remove_group(&client->dev.kobj, &tpm_tis_i2c_attr_group);
+	return 0;
+}
+
+static const struct i2c_device_id tpm_tis_i2c_id[] = {
+	{"tpm_tis_i2c", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_id);
+
+static const struct of_device_id of_tis_i2c_match[] = {
+	{ .compatible = "st,st33htpm-i2c", },
+	{ .compatible = "tcg,tpm_tis-i2c", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, of_tis_i2c_match);
+
+static const struct acpi_device_id acpi_tis_i2c_match[] = {
+	{"SMO0768", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(acpi, acpi_tis_i2c_match);
+
+static struct i2c_driver tpm_tis_i2c_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "tpm_tis_i2c",
+		.pm = &tpm_tis_i2c_pm,
+		.of_match_table = of_match_ptr(of_tis_i2c_match),
+		.acpi_match_table = ACPI_PTR(acpi_tis_i2c_match),
+	},
+	.probe = tpm_tis_i2c_probe,
+	.remove = tpm_tis_i2c_remove,
+	.id_table = tpm_tis_i2c_id,
+};
+
+module_i2c_driver(tpm_tis_i2c_driver);
+
+MODULE_DESCRIPTION("TPM Driver for native I2C access");
+MODULE_LICENSE("GPL");
-- 
2.5.0


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140
_______________________________________________
tpmdd-devel mailing list
tpmdd-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tpmdd-devel

^ permalink raw reply related	[flat|nested] 39+ messages in thread

* Re: [PATCH 00/12] Few minnor fixes, rework of tpm_tis to support tcg spi and i2c.
       [not found] ` <1458502483-16887-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (11 preceding siblings ...)
  2016-03-20 19:34   ` [PATCH 12/12] tpm/tpm_tis_i2c: Add support for i2c phy Christophe Ricard
@ 2016-03-20 21:59   ` Peter Huewe
  2016-03-21 11:13   ` Jarkko Sakkinen
  2016-03-22  5:17   ` Jarkko Sakkinen
  14 siblings, 0 replies; 39+ messages in thread
From: Peter Huewe @ 2016-03-20 21:59 UTC (permalink / raw)
  To: Christophe Ricard, jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

Thanks for helping out on this one!!
This was exactly what I planned to do.
I will review and compare it to my patch sets
Peter
-- 
Sent from my mobile

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 08/12] tpm/tpm_tis: Split tpm_tis driver into a core and TCG TIS compliant phy
       [not found]     ` <1458502483-16887-9-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2016-03-21  1:32       ` Jason Gunthorpe
       [not found]         ` <20160321013243.GA9417-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
  2016-03-22  6:23       ` Jarkko Sakkinen
  1 sibling, 1 reply; 39+ messages in thread
From: Jason Gunthorpe @ 2016-03-21  1:32 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, Peter Huewe,
	benoit.houyere-qxv4g6HH51o

On Sun, Mar 20, 2016 at 08:34:39PM +0100, Christophe Ricard wrote:
> +++ b/drivers/char/tpm/tpm.h
> @@ -142,6 +142,7 @@ struct tpm_vendor_specific {
>  
>  	int region_size;
>  	int have_region;
> +	bool itpm;
>  
>  	struct list_head list;
>  	int locality;
> @@ -149,6 +150,7 @@ struct tpm_vendor_specific {
>  	bool timeout_adjusted;
>  	unsigned long duration[3]; /* jiffies */
>  	bool duration_adjusted;
> +	bool irq_tested;
>  	void *priv;

No adding driver specific stuff to this structure.

>  	list_for_each_entry(id, &dev->pnp.ids, list)
> -		if (!strcmp(hid, id->id))
> -			return 1;
> +	if (!strcmp(hid, id->id))
> +		return 1;

useless change

> +static const struct tis_vendor_timeout_override vendor_timeout_overrides[] = {
> +	/* Atmel 3204 */
> +	{ 0x32041114, { (TIS_SHORT_TIMEOUT * 1000), (TIS_LONG_TIMEOUT * 1000),
> +			(TIS_SHORT_TIMEOUT * 1000), (TIS_SHORT_TIMEOUT * 1000) } },
> +};

This initializer should not be in a header file

> +/* Helpers - read */
> +static inline int tpm_read_bytes(struct tpm_chip *chip, u32 addr,
> +				 size_t len, u8 *res)
> +{
> +	return chip->ops->read_bytes(chip, addr, len, 1, res);
> +}

> +static inline u8 tpm_read_byte(struct tpm_chip *chip, u32 addr)

Are these all actually used? I would have thought only read32 would be
needed. Please use better names, tpm_read32,
read8, etc.

Jason

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 09/12] tpm/tpm_tis: Rework interrupt management for phy compatibility
       [not found]     ` <1458502483-16887-10-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2016-03-21  1:37       ` Jason Gunthorpe
       [not found]         ` <20160321013722.GB9417-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
  0 siblings, 1 reply; 39+ messages in thread
From: Jason Gunthorpe @ 2016-03-21  1:37 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

On Sun, Mar 20, 2016 at 08:34:40PM +0100, Christophe Ricard wrote:
> Rework interrupt handling in order to be compatible with every phy.

You need to describe this much more.

> +++ b/drivers/char/tpm/tpm-interface.c
> @@ -881,7 +881,9 @@ int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
>  	unsigned long stop;
>  	long rc;
>  	u8 status;
> +	u32 cur_intrs;
>  	bool canceled = false;
> +	bool condition;
>  
>  	/* check current status */
>  	status = chip->ops->status(chip);
> @@ -892,14 +894,17 @@ int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
>  
>  	if (chip->vendor.irq) {
>  again:
> +		cur_intrs = chip->vendor.intrs;
>  		timeout = stop - jiffies;
>  		if ((long)timeout <= 0)
>  			return -ETIME;
>  		rc = wait_event_interruptible_timeout(*queue,
> -			wait_for_tpm_stat_cond(chip, mask, check_cancel,
> -					       &canceled),
> +			cur_intrs != chip->vendor.intrs,
>  			timeout);
> -		if (rc > 0) {
> +		condition = wait_for_tpm_stat_cond(chip, mask,
> +						   check_cancel,
> +						   &canceled);
> +		if (rc > 0 && condition) {
>  			if (canceled)
>  				return -ECANCELED;
>  			return 0;

This should not be buried into a packet to tpm_tis.

How does this even work for other drivers?

> +static void tpm_tis_clear_int(struct tpm_chip *chip)

All these changes look a little unsettling.. Ordering is really
important when working with interrupts and this changes all sorts of
things.

I'd be alot happier if the current flow wasn't being changed to add
the new interfaces.

> -	if (devm_request_irq(&chip->dev, irq, tis_int_handler, flags,
> -			     dev_name(&chip->dev), chip) != 0) {
> +	if (devm_request_threaded_irq(&chip->dev, irq, NULL, tis_int_handler, flags,
> +				      dev_name(&chip->dev), chip) != 0) {

This shouldn't be changed for the lpc case either.

Jason

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 11/12] tpm: Add check_data handle to tpm_class_ops in order to check data integrity
       [not found]     ` <1458502483-16887-12-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2016-03-21  1:39       ` Jason Gunthorpe
       [not found]         ` <20160321013933.GC9417-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
  0 siblings, 1 reply; 39+ messages in thread
From: Jason Gunthorpe @ 2016-03-21  1:39 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

On Sun, Mar 20, 2016 at 08:34:42PM +0100, Christophe Ricard wrote:
> @@ -43,6 +43,7 @@ struct tpm_class_ops {
>  	u8 (*status) (struct tpm_chip *chip);
>  	bool (*update_timeouts)(struct tpm_chip *chip,
>  				unsigned long *timeout_cap);
> +	bool (*check_data)(struct tpm_chip *chip, u8 *buf, size_t len);
>  	int (*read_bytes)(struct tpm_chip *chip, u32 addr, size_t len,
>  			  u8 size, u8 *dst);

Don't add tis specific functions to this structure.

Jason

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 00/12] Few minnor fixes, rework of tpm_tis to support tcg spi and i2c.
       [not found] ` <1458502483-16887-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (12 preceding siblings ...)
  2016-03-20 21:59   ` [PATCH 00/12] Few minnor fixes, rework of tpm_tis to support tcg spi and i2c Peter Huewe
@ 2016-03-21 11:13   ` Jarkko Sakkinen
  2016-03-22  5:17   ` Jarkko Sakkinen
  14 siblings, 0 replies; 39+ messages in thread
From: Jarkko Sakkinen @ 2016-03-21 11:13 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

On Sun, Mar 20, 2016 at 08:34:31PM +0100, Christophe Ricard wrote:
> Hi Jarkko,
> 
> Please find in this serie some few minnor fixes as well as some more work around the
> tpm_tis driver.
> 
> This work is based on Peter Huewe's proposal in October 30th 2015:
> https://patchwork.ozlabs.org/patch/538179/
> 
> I have tried to keep Peter's credits on related patches.
> 
> The idea is to have one main tpm_tis_core which would keep a common tpm_tis logic for
> all physical layers(i2c, spi, legacy/lpc).
> This tpm_tis_core can be reused by other drivers (such as st33zp24...) and would
> potentially easy the maintenance.
> 
> It offers support for LPC (tpm_tis), SPI (tpm_tis_spi) and I2C (tpm_tis_i2c) following
> ongoing or available TCG specifications
> 
> SPI layer is supporting wait state/Flow Control as describe in the TCG PTP specification
> (chapter 6.4.5 Flow Control).
> 
> I2C layer is following TCG on going and almost finalized specification.
> 
> Physical layer i2c and spi are tested using STMicro TPM's against Minnowboard, RaspberryPi
> and Beagleboard xM in both polling and interrupt mode.
> 
> For now, i haven't been able to test the LPC/legacy layer but assume it should work.
> 
> Any comment welcome :).

I still have a couple of patches to review and test for vTPM.
After that I can look into this.

/Jarkko


> Best Regards
> Christophe
> 
> Christophe Ricard (12):
>   tpm/st33zp24/i2c: Drop two useless checks in ACPI probe path
>   tpm/st33zp24/spi: Drop two useless checks in ACPI probe path
>   tpm: Add include guards in tpm.h
>   tpm/st33zp24: Remove unneeded tpm_reg in get_burstcount
>   tpm: Add tpm_set_vendordata and tpm_get_vendordata
>   devicetree: Add infineon to vendor-prefix.txt
>   devicetree: Add Trusted Computing Group to vendor-prefix.txt
>   tpm/tpm_tis: Split tpm_tis driver into a core and TCG TIS compliant
>     phy
>   tpm/tpm_tis: Rework interrupt management for phy compatibility
>   tpm/tpm_tis_spi: Add support for spi phy
>   tpm: Add check_data handle to tpm_class_ops in order to check data
>     integrity
>   tpm/tpm_tis_i2c: Add support for i2c phy
> 
>  .../bindings/security/tpm/tpm_tis_i2c.txt          |  30 +
>  .../bindings/security/tpm/tpm_tis_spi.txt          |  28 +
>  .../devicetree/bindings/vendor-prefixes.txt        |   2 +
>  drivers/char/tpm/Kconfig                           |  24 +-
>  drivers/char/tpm/Makefile                          |   4 +-
>  drivers/char/tpm/st33zp24/i2c.c                    |  13 +-
>  drivers/char/tpm/st33zp24/spi.c                    |  13 +-
>  drivers/char/tpm/st33zp24/st33zp24.c               |  36 +-
>  drivers/char/tpm/tpm-interface.c                   |  11 +-
>  drivers/char/tpm/tpm.h                             |  20 +-
>  drivers/char/tpm/tpm_ibmvtpm.c                     |   8 +-
>  drivers/char/tpm/tpm_tis.c                         | 803 ++-------------------
>  drivers/char/tpm/tpm_tis_core.c                    | 763 ++++++++++++++++++++
>  drivers/char/tpm/tpm_tis_core.h                    | 166 +++++
>  drivers/char/tpm/tpm_tis_i2c.c                     | 499 +++++++++++++
>  drivers/char/tpm/tpm_tis_spi.c                     | 279 +++++++
>  drivers/char/tpm/xen-tpmfront.c                    |  14 +-
>  include/linux/tpm.h                                |   5 +
>  18 files changed, 1908 insertions(+), 810 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/security/tpm/tpm_tis_i2c.txt
>  create mode 100644 Documentation/devicetree/bindings/security/tpm/tpm_tis_spi.txt
>  create mode 100644 drivers/char/tpm/tpm_tis_core.c
>  create mode 100644 drivers/char/tpm/tpm_tis_core.h
>  create mode 100644 drivers/char/tpm/tpm_tis_i2c.c
>  create mode 100644 drivers/char/tpm/tpm_tis_spi.c
> 
> -- 
> 2.5.0
> 

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 11/12] tpm: Add check_data handle to tpm_class_ops in order to check data integrity
       [not found]         ` <20160321013933.GC9417-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
@ 2016-03-21 17:44           ` Christophe Ricard
  0 siblings, 0 replies; 39+ messages in thread
From: Christophe Ricard @ 2016-03-21 17:44 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Jean-Luc BLANC, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Christophe RICARD,
	Benoit HOUYERE


[-- Attachment #1.1: Type: text/plain, Size: 863 bytes --]

Hi Jason,

Just trying to understand. How check_data would be more specific than
update_timeouts only used by the tis part as well ?
Do you expect to have a tis_ops specific structure ?

Best Regards
Christophe

2016-03-21 2:39 GMT+01:00 Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>:

> On Sun, Mar 20, 2016 at 08:34:42PM +0100, Christophe Ricard wrote:
> > @@ -43,6 +43,7 @@ struct tpm_class_ops {
> >       u8 (*status) (struct tpm_chip *chip);
> >       bool (*update_timeouts)(struct tpm_chip *chip,
> >                               unsigned long *timeout_cap);
> > +     bool (*check_data)(struct tpm_chip *chip, u8 *buf, size_t len);
> >       int (*read_bytes)(struct tpm_chip *chip, u32 addr, size_t len,
> >                         u8 size, u8 *dst);
>
> Don't add tis specific functions to this structure.
>
> Jason
>

[-- Attachment #1.2: Type: text/html, Size: 1421 bytes --]

[-- Attachment #2: Type: text/plain, Size: 291 bytes --]

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

[-- Attachment #3: Type: text/plain, Size: 192 bytes --]

_______________________________________________
tpmdd-devel mailing list
tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/tpmdd-devel

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 09/12] tpm/tpm_tis: Rework interrupt management for phy compatibility
       [not found]         ` <20160321013722.GB9417-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
@ 2016-03-21 17:45           ` Christophe Ricard
  0 siblings, 0 replies; 39+ messages in thread
From: Christophe Ricard @ 2016-03-21 17:45 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Jean-Luc BLANC, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Christophe RICARD,
	Benoit HOUYERE


[-- Attachment #1.1: Type: text/plain, Size: 2526 bytes --]

Ok, let me look into that a bit deeper.

2016-03-21 2:37 GMT+01:00 Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>:

> On Sun, Mar 20, 2016 at 08:34:40PM +0100, Christophe Ricard wrote:
> > Rework interrupt handling in order to be compatible with every phy.
>
> You need to describe this much more.
>
> > +++ b/drivers/char/tpm/tpm-interface.c
> > @@ -881,7 +881,9 @@ int wait_for_tpm_stat(struct tpm_chip *chip, u8
> mask, unsigned long timeout,
> >       unsigned long stop;
> >       long rc;
> >       u8 status;
> > +     u32 cur_intrs;
> >       bool canceled = false;
> > +     bool condition;
> >
> >       /* check current status */
> >       status = chip->ops->status(chip);
> > @@ -892,14 +894,17 @@ int wait_for_tpm_stat(struct tpm_chip *chip, u8
> mask, unsigned long timeout,
> >
> >       if (chip->vendor.irq) {
> >  again:
> > +             cur_intrs = chip->vendor.intrs;
> >               timeout = stop - jiffies;
> >               if ((long)timeout <= 0)
> >                       return -ETIME;
> >               rc = wait_event_interruptible_timeout(*queue,
> > -                     wait_for_tpm_stat_cond(chip, mask, check_cancel,
> > -                                            &canceled),
> > +                     cur_intrs != chip->vendor.intrs,
> >                       timeout);
> > -             if (rc > 0) {
> > +             condition = wait_for_tpm_stat_cond(chip, mask,
> > +                                                check_cancel,
> > +                                                &canceled);
> > +             if (rc > 0 && condition) {
> >                       if (canceled)
> >                               return -ECANCELED;
> >                       return 0;
>
> This should not be buried into a packet to tpm_tis.
>
> How does this even work for other drivers?
>
> > +static void tpm_tis_clear_int(struct tpm_chip *chip)
>
> All these changes look a little unsettling.. Ordering is really
> important when working with interrupts and this changes all sorts of
> things.
>
> I'd be alot happier if the current flow wasn't being changed to add
> the new interfaces.
>
> > -     if (devm_request_irq(&chip->dev, irq, tis_int_handler, flags,
> > -                          dev_name(&chip->dev), chip) != 0) {
> > +     if (devm_request_threaded_irq(&chip->dev, irq, NULL,
> tis_int_handler, flags,
> > +                                   dev_name(&chip->dev), chip) != 0) {
>
> This shouldn't be changed for the lpc case either.
>
> Jason
>

[-- Attachment #1.2: Type: text/html, Size: 3641 bytes --]

[-- Attachment #2: Type: text/plain, Size: 291 bytes --]

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

[-- Attachment #3: Type: text/plain, Size: 192 bytes --]

_______________________________________________
tpmdd-devel mailing list
tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/tpmdd-devel

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 08/12] tpm/tpm_tis: Split tpm_tis driver into a core and TCG TIS compliant phy
       [not found]         ` <20160321013243.GA9417-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
@ 2016-03-21 22:35           ` Christophe Ricard
       [not found]             ` <56F0774F.7040707-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 39+ messages in thread
From: Christophe Ricard @ 2016-03-21 22:35 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, Peter Huewe,
	benoit.houyere-qxv4g6HH51o

Hi Jason,

My answers/questions below.

Best Regards
Christophe

On 21/03/2016 02:32, Jason Gunthorpe wrote:
> On Sun, Mar 20, 2016 at 08:34:39PM +0100, Christophe Ricard wrote:
>> +++ b/drivers/char/tpm/tpm.h
>> @@ -142,6 +142,7 @@ struct tpm_vendor_specific {
>>   
>>   	int region_size;
>>   	int have_region;
>> +	bool itpm;
>>   
>>   	struct list_head list;
>>   	int locality;
>> @@ -149,6 +150,7 @@ struct tpm_vendor_specific {
>>   	bool timeout_adjusted;
>>   	unsigned long duration[3]; /* jiffies */
>>   	bool duration_adjusted;
>> +	bool irq_tested;
>>   	void *priv;
> No adding driver specific stuff to this structure.
I suppose irq_tested is fine because it is common all drivers and 
related to irq management. I guess it can be moved below irq field.
I somewhat understand your mean for itpm.
I believe it is specific for the legacy/lpc/0xfed4xxxx addressing mode. 
Can you confirm ?

For itpm workaround, i would like to use 2 additional specific fields in 
tpm_class_ops called req_expected_val and req_expected_mask.
req_expected_val and req_expected_mask would be set in all phys with 
TPM_STS_DATA_EXPECT.
An additional tpm_class_ops ops called for example tpm_postprobe for 
additional phys specific operations handling in tpm_tis the itpm workaround.
req_expected_val and req_expected_mask would be set to 0 in tpm_tis in 
case itpm is set to true and probe_itpm set itpm to true.

This would remove the need of any itpm mention in the tpm_tis_core 
layer. What do you think ?
>
>>   	list_for_each_entry(id, &dev->pnp.ids, list)
>> -		if (!strcmp(hid, id->id))
>> -			return 1;
>> +	if (!strcmp(hid, id->id))
>> +		return 1;
> useless change
Ok
>> +static const struct tis_vendor_timeout_override vendor_timeout_overrides[] = {
>> +	/* Atmel 3204 */
>> +	{ 0x32041114, { (TIS_SHORT_TIMEOUT * 1000), (TIS_LONG_TIMEOUT * 1000),
>> +			(TIS_SHORT_TIMEOUT * 1000), (TIS_SHORT_TIMEOUT * 1000) } },
>> +};
> This initializer should not be in a header file
I will move it in tpm_tis_core.c
>
>> +/* Helpers - read */
>> +static inline int tpm_read_bytes(struct tpm_chip *chip, u32 addr,
>> +				 size_t len, u8 *res)
>> +{
>> +	return chip->ops->read_bytes(chip, addr, len, 1, res);
>> +}
>> +static inline u8 tpm_read_byte(struct tpm_chip *chip, u32 addr)
> Are these all actually used? I would have thought only read32 would be
> needed. Please use better names, tpm_read32,
> read8, etc.
I did a quick check of the complete set and found all of them are used.
> Jason


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 08/12] tpm/tpm_tis: Split tpm_tis driver into a core and TCG TIS compliant phy
       [not found]             ` <56F0774F.7040707-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2016-03-21 23:26               ` Jason Gunthorpe
  0 siblings, 0 replies; 39+ messages in thread
From: Jason Gunthorpe @ 2016-03-21 23:26 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, Peter Huewe,
	benoit.houyere-qxv4g6HH51o

> >On Sun, Mar 20, 2016 at 08:34:39PM +0100, Christophe Ricard wrote:
> >>+++ b/drivers/char/tpm/tpm.h
> >>@@ -142,6 +142,7 @@ struct tpm_vendor_specific {
> >>  	int region_size;
> >>  	int have_region;
> >>+	bool itpm;
> >>  	struct list_head list;
> >>  	int locality;
> >>@@ -149,6 +150,7 @@ struct tpm_vendor_specific {
> >>  	bool timeout_adjusted;
> >>  	unsigned long duration[3]; /* jiffies */
> >>  	bool duration_adjusted;
> >>+	bool irq_tested;
> >>  	void *priv;
> >No adding driver specific stuff to this structure.
> I suppose irq_tested is fine because it is common all drivers and related to
> irq management. I guess it can be moved below irq field.

No, we are trying to get rid of the vendor_specific structure, it is a
mistake.

You need to add some kind of new structure shared between the tpm_tis
shared code and the tpm_tis phy code. Put all this stuff there. If it
isn't used by the core code it should not be in the core structures.

> I somewhat understand your mean for itpm.
> I believe it is specific for the legacy/lpc/0xfed4xxxx addressing mode. Can
> you confirm ?

Yes, there is a specific device with bad behavior that detects.

Jason

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 02/12] tpm/st33zp24/spi: Drop two useless checks in ACPI probe path
       [not found]     ` <1458502483-16887-3-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2016-03-22  5:10       ` Jarkko Sakkinen
  0 siblings, 0 replies; 39+ messages in thread
From: Jarkko Sakkinen @ 2016-03-22  5:10 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

On Sun, Mar 20, 2016 at 08:34:33PM +0100, Christophe Ricard wrote:
> When st33zp24_spi_acpi_request_resources() gets called we
> already know that the entries in ->acpi_match_table have matched ACPI ID
> of the device.
> In addition spi_device pointer cannot be NULL in any case (otherwise I2C
> core would not call ->probe() for the driver in the first place).
> 
> Drop the two useless checks from the driver.
> 
> Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>

How this patch and another similar patch is related to logical change
described in the cover letter? I'm not saying these changes are wrong
but if they are not related then they should not be in the patch set.

/Jarkko

> ---
>  drivers/char/tpm/st33zp24/spi.c | 13 +------------
>  1 file changed, 1 insertion(+), 12 deletions(-)
> 
> diff --git a/drivers/char/tpm/st33zp24/spi.c b/drivers/char/tpm/st33zp24/spi.c
> index 6be51ac..608dbc6 100644
> --- a/drivers/char/tpm/st33zp24/spi.c
> +++ b/drivers/char/tpm/st33zp24/spi.c
> @@ -232,19 +232,8 @@ static const struct st33zp24_phy_ops spi_phy_ops = {
>  static int st33zp24_spi_acpi_request_resources(struct spi_device *spi_dev)
>  {
>  	struct st33zp24_spi_phy *phy = spi_get_drvdata(spi_dev);
> -	const struct acpi_device_id *id;
>  	struct gpio_desc *gpiod_lpcpd;
> -	struct device *dev;
> -
> -	if (!spi_dev)
> -		return -EINVAL;
> -
> -	dev = &spi_dev->dev;
> -
> -	/* Match the struct device against a given list of ACPI IDs */
> -	id = acpi_match_device(dev->driver->acpi_match_table, dev);
> -	if (!id)
> -		return -ENODEV;
> +	struct device *dev = &spi_dev->dev;
>  
>  	/* Get LPCPD GPIO from ACPI */
>  	gpiod_lpcpd = devm_gpiod_get_index(dev, "TPM IO LPCPD", 1,
> -- 
> 2.5.0
> 

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 03/12] tpm: Add include guards in tpm.h
       [not found]     ` <1458502483-16887-4-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2016-03-22  5:13       ` Jarkko Sakkinen
  0 siblings, 0 replies; 39+ messages in thread
From: Jarkko Sakkinen @ 2016-03-22  5:13 UTC (permalink / raw)
  To: Christophe Ricard, g
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, Peter Huewe,
	benoit.houyere-qxv4g6HH51o

On Sun, Mar 20, 2016 at 08:34:34PM +0100, Christophe Ricard wrote:
> Add missing include guards in tpm.h
> 
> Signed-off-by: Peter Huewe <peter.huewe-d0qZbvYSIPpWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>

Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>

/Jarkko

> ---
>  drivers/char/tpm/tpm.h | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> index 928b47f..28a0c17 100644
> --- a/drivers/char/tpm/tpm.h
> +++ b/drivers/char/tpm/tpm.h
> @@ -19,6 +19,10 @@
>   * License.
>   *
>   */
> +
> +#ifndef __TPM_H__
> +#define __TPM_H__
> +
>  #include <linux/module.h>
>  #include <linux/delay.h>
>  #include <linux/fs.h>
> @@ -548,3 +552,4 @@ extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32);
>  extern int tpm2_do_selftest(struct tpm_chip *chip);
>  extern int tpm2_gen_interrupt(struct tpm_chip *chip);
>  extern int tpm2_probe(struct tpm_chip *chip);
> +#endif
> -- 
> 2.5.0
> 

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 00/12] Few minnor fixes, rework of tpm_tis to support tcg spi and i2c.
       [not found] ` <1458502483-16887-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
                     ` (13 preceding siblings ...)
  2016-03-21 11:13   ` Jarkko Sakkinen
@ 2016-03-22  5:17   ` Jarkko Sakkinen
  14 siblings, 0 replies; 39+ messages in thread
From: Jarkko Sakkinen @ 2016-03-22  5:17 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

On Sun, Mar 20, 2016 at 08:34:31PM +0100, Christophe Ricard wrote:
> Hi Jarkko,
> 
> Please find in this serie some few minnor fixes as well as some more work around the
> tpm_tis driver.
> 
> This work is based on Peter Huewe's proposal in October 30th 2015:
> https://patchwork.ozlabs.org/patch/538179/
> 
> I have tried to keep Peter's credits on related patches.
> 
> The idea is to have one main tpm_tis_core which would keep a common tpm_tis logic for
> all physical layers(i2c, spi, legacy/lpc).
> This tpm_tis_core can be reused by other drivers (such as st33zp24...) and would
> potentially easy the maintenance.
> 
> It offers support for LPC (tpm_tis), SPI (tpm_tis_spi) and I2C (tpm_tis_i2c) following
> ongoing or available TCG specifications
> 
> SPI layer is supporting wait state/Flow Control as describe in the TCG PTP specification
> (chapter 6.4.5 Flow Control).
> 
> I2C layer is following TCG on going and almost finalized specification.
> 
> Physical layer i2c and spi are tested using STMicro TPM's against Minnowboard, RaspberryPi
> and Beagleboard xM in both polling and interrupt mode.
> 
> For now, i haven't been able to test the LPC/legacy layer but assume it should work.
> 
> Any comment welcome :).

Some of the patches are good but in general I think the patch set itself
is not legit. You can see it alreaady from this description. Patches
should be somehow logically related. Now it's "dump of stuff that I've
done recently". Not a nice thing to review in any sense of the word...


> Best Regards
> Christophe

/Jarkko

> 
> Christophe Ricard (12):
>   tpm/st33zp24/i2c: Drop two useless checks in ACPI probe path
>   tpm/st33zp24/spi: Drop two useless checks in ACPI probe path
>   tpm: Add include guards in tpm.h
>   tpm/st33zp24: Remove unneeded tpm_reg in get_burstcount
>   tpm: Add tpm_set_vendordata and tpm_get_vendordata
>   devicetree: Add infineon to vendor-prefix.txt
>   devicetree: Add Trusted Computing Group to vendor-prefix.txt
>   tpm/tpm_tis: Split tpm_tis driver into a core and TCG TIS compliant
>     phy
>   tpm/tpm_tis: Rework interrupt management for phy compatibility
>   tpm/tpm_tis_spi: Add support for spi phy
>   tpm: Add check_data handle to tpm_class_ops in order to check data
>     integrity
>   tpm/tpm_tis_i2c: Add support for i2c phy
> 
>  .../bindings/security/tpm/tpm_tis_i2c.txt          |  30 +
>  .../bindings/security/tpm/tpm_tis_spi.txt          |  28 +
>  .../devicetree/bindings/vendor-prefixes.txt        |   2 +
>  drivers/char/tpm/Kconfig                           |  24 +-
>  drivers/char/tpm/Makefile                          |   4 +-
>  drivers/char/tpm/st33zp24/i2c.c                    |  13 +-
>  drivers/char/tpm/st33zp24/spi.c                    |  13 +-
>  drivers/char/tpm/st33zp24/st33zp24.c               |  36 +-
>  drivers/char/tpm/tpm-interface.c                   |  11 +-
>  drivers/char/tpm/tpm.h                             |  20 +-
>  drivers/char/tpm/tpm_ibmvtpm.c                     |   8 +-
>  drivers/char/tpm/tpm_tis.c                         | 803 ++-------------------
>  drivers/char/tpm/tpm_tis_core.c                    | 763 ++++++++++++++++++++
>  drivers/char/tpm/tpm_tis_core.h                    | 166 +++++
>  drivers/char/tpm/tpm_tis_i2c.c                     | 499 +++++++++++++
>  drivers/char/tpm/tpm_tis_spi.c                     | 279 +++++++
>  drivers/char/tpm/xen-tpmfront.c                    |  14 +-
>  include/linux/tpm.h                                |   5 +
>  18 files changed, 1908 insertions(+), 810 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/security/tpm/tpm_tis_i2c.txt
>  create mode 100644 Documentation/devicetree/bindings/security/tpm/tpm_tis_spi.txt
>  create mode 100644 drivers/char/tpm/tpm_tis_core.c
>  create mode 100644 drivers/char/tpm/tpm_tis_core.h
>  create mode 100644 drivers/char/tpm/tpm_tis_i2c.c
>  create mode 100644 drivers/char/tpm/tpm_tis_spi.c
> 
> -- 
> 2.5.0
> 

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 04/12] tpm/st33zp24: Remove unneeded tpm_reg in get_burstcount
       [not found]     ` <1458502483-16887-5-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2016-03-22  6:16       ` Jarkko Sakkinen
       [not found]         ` <20160322061650.GA4058-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 39+ messages in thread
From: Jarkko Sakkinen @ 2016-03-22  6:16 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

On Sun, Mar 20, 2016 at 08:34:35PM +0100, Christophe Ricard wrote:
> We can get rid of tpm_reg variable in get_burstcount.

Maybe you should send these st33zp24 fixes as a separate patch set
as they are all unrelated to the rework.

/Jarkko

> Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
> ---
>  drivers/char/tpm/st33zp24/st33zp24.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c
> index 944d279..9e91ca7 100644
> --- a/drivers/char/tpm/st33zp24/st33zp24.c
> +++ b/drivers/char/tpm/st33zp24/st33zp24.c
> @@ -208,21 +208,21 @@ static int get_burstcount(struct tpm_chip *chip)
>  {
>  	unsigned long stop;
>  	int burstcnt, status;
> -	u8 tpm_reg, temp;
> +	u8 temp;
>  	struct st33zp24_dev *tpm_dev;
>  
>  	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
>  
>  	stop = jiffies + chip->vendor.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;
>  
> -- 
> 2.5.0
> 

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 05/12] tpm: Add tpm_set_vendordata and tpm_get_vendordata
       [not found]     ` <1458502483-16887-6-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
@ 2016-03-22  6:20       ` Jarkko Sakkinen
       [not found]         ` <20160322062001.GB4058-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 39+ messages in thread
From: Jarkko Sakkinen @ 2016-03-22  6:20 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

On Sun, Mar 20, 2016 at 08:34:36PM +0100, Christophe Ricard wrote:
> Remove TPM_VPRIV macro and replace with tpm_set_vendordata and
> tpm_get_vendordata.

NAK. These unnecessary wrapper functions make code just harder to read.
I'd rather accept a patch that would drop TPM_VPRIV and not introduce
new clutter.

/Jarkko

> Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
> ---
>  drivers/char/tpm/st33zp24/st33zp24.c | 26 +++++++++++++-------------
>  drivers/char/tpm/tpm.h               | 12 ++++++++++--
>  drivers/char/tpm/tpm_ibmvtpm.c       |  8 ++++----
>  drivers/char/tpm/tpm_tis.c           |  2 +-
>  drivers/char/tpm/xen-tpmfront.c      | 14 +++++++-------
>  5 files changed, 35 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c
> index 9e91ca7..dc2d0f3 100644
> --- a/drivers/char/tpm/st33zp24/st33zp24.c
> +++ b/drivers/char/tpm/st33zp24/st33zp24.c
> @@ -105,7 +105,7 @@ static void st33zp24_cancel(struct tpm_chip *chip)
>  	struct st33zp24_dev *tpm_dev;
>  	u8 data;
>  
> -	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> +	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>  
>  	data = TPM_STS_COMMAND_READY;
>  	tpm_dev->ops->send(tpm_dev->phy_id, TPM_STS, &data, 1);
> @@ -121,7 +121,7 @@ static u8 st33zp24_status(struct tpm_chip *chip)
>  	struct st33zp24_dev *tpm_dev;
>  	u8 data;
>  
> -	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> +	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>  
>  	tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS, &data, 1);
>  	return data;
> @@ -138,7 +138,7 @@ static int check_locality(struct tpm_chip *chip)
>  	u8 data;
>  	u8 status;
>  
> -	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> +	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>  
>  	status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
>  	if (status && (data &
> @@ -164,7 +164,7 @@ static int request_locality(struct tpm_chip *chip)
>  	if (check_locality(chip) == chip->vendor.locality)
>  		return chip->vendor.locality;
>  
> -	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> +	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>  
>  	data = TPM_ACCESS_REQUEST_USE;
>  	ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
> @@ -193,7 +193,7 @@ static void release_locality(struct tpm_chip *chip)
>  	struct st33zp24_dev *tpm_dev;
>  	u8 data;
>  
> -	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> +	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>  	data = TPM_ACCESS_ACTIVE_LOCALITY;
>  
>  	tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
> @@ -211,7 +211,7 @@ static int get_burstcount(struct tpm_chip *chip)
>  	u8 temp;
>  	struct st33zp24_dev *tpm_dev;
>  
> -	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> +	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>  
>  	stop = jiffies + chip->vendor.timeout_d;
>  	do {
> @@ -279,7 +279,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
>  	u8 status;
>  	struct st33zp24_dev *tpm_dev;
>  
> -	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> +	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>  
>  	/* check current status */
>  	status = st33zp24_status(chip);
> @@ -340,7 +340,7 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
>  	int size = 0, burstcnt, len, ret;
>  	struct st33zp24_dev *tpm_dev;
>  
> -	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> +	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>  
>  	while (size < count &&
>  	       wait_for_stat(chip,
> @@ -372,7 +372,7 @@ 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);
> +	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>  
>  	tpm_dev->intrs++;
>  	wake_up_interruptible(&chip->vendor.read_queue);
> @@ -404,7 +404,7 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf,
>  	if (len < TPM_HEADER_SIZE)
>  		return -EBUSY;
>  
> -	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> +	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>  
>  	ret = request_locality(chip);
>  	if (ret < 0)
> @@ -565,7 +565,7 @@ int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops,
>  	if (!tpm_dev)
>  		return -ENOMEM;
>  
> -	TPM_VPRIV(chip) = tpm_dev;
> +	tpm_set_vendordata(chip, tpm_dev);
>  	tpm_dev->phy_id = phy_id;
>  	tpm_dev->ops = ops;
>  
> @@ -653,7 +653,7 @@ int st33zp24_pm_suspend(struct device *dev)
>  	struct st33zp24_dev *tpm_dev;
>  	int ret = 0;
>  
> -	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> +	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>  
>  	if (gpio_is_valid(tpm_dev->io_lpcpd))
>  		gpio_set_value(tpm_dev->io_lpcpd, 0);
> @@ -675,7 +675,7 @@ int st33zp24_pm_resume(struct device *dev)
>  	struct st33zp24_dev *tpm_dev;
>  	int ret = 0;
>  
> -	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> +	tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>  
>  	if (gpio_is_valid(tpm_dev->io_lpcpd)) {
>  		gpio_set_value(tpm_dev->io_lpcpd, 1);
> diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> index 28a0c17..6a973b9 100644
> --- a/drivers/char/tpm/tpm.h
> +++ b/drivers/char/tpm/tpm.h
> @@ -157,8 +157,6 @@ struct tpm_vendor_specific {
>  	u16 manufacturer_id;
>  };
>  
> -#define TPM_VPRIV(c)     ((c)->vendor.priv)
> -
>  #define TPM_VID_INTEL    0x8086
>  #define TPM_VID_WINBOND  0x1050
>  #define TPM_VID_STM      0x104A
> @@ -203,6 +201,16 @@ struct tpm_chip {
>  
>  #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
>  
> +static inline void tpm_set_vendordata(struct tpm_chip *chip, void *data)
> +{
> +	chip->vendor.priv = data;
> +}
> +
> +static inline void *tpm_get_vendordata(struct tpm_chip *chip)
> +{
> +	return chip->vendor.priv;
> +}
> +
>  static inline int tpm_read_index(int base, int index)
>  {
>  	outb(index, base);
> diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c
> index b0a9a9e..c8b1643 100644
> --- a/drivers/char/tpm/tpm_ibmvtpm.c
> +++ b/drivers/char/tpm/tpm_ibmvtpm.c
> @@ -64,7 +64,7 @@ static struct ibmvtpm_dev *ibmvtpm_get_data(const struct device *dev)
>  {
>  	struct tpm_chip *chip = dev_get_drvdata(dev);
>  	if (chip)
> -		return (struct ibmvtpm_dev *)TPM_VPRIV(chip);
> +		return (struct ibmvtpm_dev *)tpm_get_vendordata(chip);
>  	return NULL;
>  }
>  
> @@ -83,7 +83,7 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
>  	u16 len;
>  	int sig;
>  
> -	ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
> +	ibmvtpm = (struct ibmvtpm_dev *)tpm_get_vendordata(chip);
>  
>  	if (!ibmvtpm->rtce_buf) {
>  		dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
> @@ -127,7 +127,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
>  	__be64 *word = (__be64 *)&crq;
>  	int rc, sig;
>  
> -	ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
> +	ibmvtpm = (struct ibmvtpm_dev *)tpm_get_vendordata(chip);
>  
>  	if (!ibmvtpm->rtce_buf) {
>  		dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
> @@ -643,7 +643,7 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
>  
>  	crq_q->index = 0;
>  
> -	TPM_VPRIV(chip) = (void *)ibmvtpm;
> +	tpm_set_vendordata(chip, (void *)ibmvtpm);
>  
>  	spin_lock_init(&ibmvtpm->rtce_lock);
>  
> diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
> index eed3bf5..607fa3f 100644
> --- a/drivers/char/tpm/tpm_tis.c
> +++ b/drivers/char/tpm/tpm_tis.c
> @@ -678,7 +678,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
>  	if (IS_ERR(chip))
>  		return PTR_ERR(chip);
>  
> -	chip->vendor.priv = priv;
> +	tpm_set_vendordata(chip, priv);
>  #ifdef CONFIG_ACPI
>  	chip->acpi_dev_handle = acpi_dev_handle;
>  #endif
> diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c
> index 3111f27..c472fd8 100644
> --- a/drivers/char/tpm/xen-tpmfront.c
> +++ b/drivers/char/tpm/xen-tpmfront.c
> @@ -39,7 +39,7 @@ enum status_bits {
>  
>  static u8 vtpm_status(struct tpm_chip *chip)
>  {
> -	struct tpm_private *priv = TPM_VPRIV(chip);
> +	struct tpm_private *priv = tpm_get_vendordata(chip);
>  	switch (priv->shr->state) {
>  	case VTPM_STATE_IDLE:
>  		return VTPM_STATUS_IDLE | VTPM_STATUS_CANCELED;
> @@ -60,7 +60,7 @@ static bool vtpm_req_canceled(struct tpm_chip *chip, u8 status)
>  
>  static void vtpm_cancel(struct tpm_chip *chip)
>  {
> -	struct tpm_private *priv = TPM_VPRIV(chip);
> +	struct tpm_private *priv = tpm_get_vendordata(chip);
>  	priv->shr->state = VTPM_STATE_CANCEL;
>  	wmb();
>  	notify_remote_via_evtchn(priv->evtchn);
> @@ -73,7 +73,7 @@ static unsigned int shr_data_offset(struct vtpm_shared_page *shr)
>  
>  static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
>  {
> -	struct tpm_private *priv = TPM_VPRIV(chip);
> +	struct tpm_private *priv = tpm_get_vendordata(chip);
>  	struct vtpm_shared_page *shr = priv->shr;
>  	unsigned int offset = shr_data_offset(shr);
>  
> @@ -115,7 +115,7 @@ static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
>  
>  static int vtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
>  {
> -	struct tpm_private *priv = TPM_VPRIV(chip);
> +	struct tpm_private *priv = tpm_get_vendordata(chip);
>  	struct vtpm_shared_page *shr = priv->shr;
>  	unsigned int offset = shr_data_offset(shr);
>  	size_t length = shr->length;
> @@ -182,7 +182,7 @@ static int setup_chip(struct device *dev, struct tpm_private *priv)
>  	init_waitqueue_head(&chip->vendor.read_queue);
>  
>  	priv->chip = chip;
> -	TPM_VPRIV(chip) = priv;
> +	tpm_set_vendordata(chip, priv);
>  
>  	return 0;
>  }
> @@ -318,10 +318,10 @@ static int tpmfront_probe(struct xenbus_device *dev,
>  static int tpmfront_remove(struct xenbus_device *dev)
>  {
>  	struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
> -	struct tpm_private *priv = TPM_VPRIV(chip);
> +	struct tpm_private *priv = tpm_get_vendordata(chip);
>  	tpm_chip_unregister(chip);
>  	ring_free(priv);
> -	TPM_VPRIV(chip) = NULL;
> +	tpm_set_vendordata(chip, NULL);
>  	return 0;
>  }
>  
> -- 
> 2.5.0
> 

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 04/12] tpm/st33zp24: Remove unneeded tpm_reg in get_burstcount
       [not found]         ` <20160322061650.GA4058-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
@ 2016-03-22  6:21           ` Christophe Ricard
  0 siblings, 0 replies; 39+ messages in thread
From: Christophe Ricard @ 2016-03-22  6:21 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

Hi Jarkko,

ok. Will do.

Best Regards
Christophe

On 22/03/2016 07:16, Jarkko Sakkinen wrote:
> On Sun, Mar 20, 2016 at 08:34:35PM +0100, Christophe Ricard wrote:
>> We can get rid of tpm_reg variable in get_burstcount.
> Maybe you should send these st33zp24 fixes as a separate patch set
> as they are all unrelated to the rework.
>
> /Jarkko
>
>> Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
>> ---
>>   drivers/char/tpm/st33zp24/st33zp24.c | 10 +++++-----
>>   1 file changed, 5 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c
>> index 944d279..9e91ca7 100644
>> --- a/drivers/char/tpm/st33zp24/st33zp24.c
>> +++ b/drivers/char/tpm/st33zp24/st33zp24.c
>> @@ -208,21 +208,21 @@ static int get_burstcount(struct tpm_chip *chip)
>>   {
>>   	unsigned long stop;
>>   	int burstcnt, status;
>> -	u8 tpm_reg, temp;
>> +	u8 temp;
>>   	struct st33zp24_dev *tpm_dev;
>>   
>>   	tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
>>   
>>   	stop = jiffies + chip->vendor.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;
>>   
>> -- 
>> 2.5.0
>>


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 08/12] tpm/tpm_tis: Split tpm_tis driver into a core and TCG TIS compliant phy
       [not found]     ` <1458502483-16887-9-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
  2016-03-21  1:32       ` Jason Gunthorpe
@ 2016-03-22  6:23       ` Jarkko Sakkinen
  1 sibling, 0 replies; 39+ messages in thread
From: Jarkko Sakkinen @ 2016-03-22  6:23 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, Peter Huewe,
	benoit.houyere-qxv4g6HH51o

On Sun, Mar 20, 2016 at 08:34:39PM +0100, Christophe Ricard wrote:
> To avoid code duplication between the old tpm_tis and the new and future
> native tcg tis driver(ie: spi, i2c...), the tpm_tis driver was reworked,
> so that all common logic is extracted and can be reused from all drivers.
> 
> The core methods can also be used from other TIS like drivers.

As Jason already stated this patch is taking things to wrong direction.
We want to eventually get rid of tpm_vendor_specific. I'm not going to
do a more detailed review because the big picture is wrong.

/Jarkko

> Signed-off-by: Peter Huewe <peter.huewe-d0qZbvYSIPpWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
> ---
>  drivers/char/tpm/Makefile       |   2 +-
>  drivers/char/tpm/tpm.h          |   2 +
>  drivers/char/tpm/tpm_tis.c      | 803 +++-------------------------------------
>  drivers/char/tpm/tpm_tis_core.c | 728 ++++++++++++++++++++++++++++++++++++
>  drivers/char/tpm/tpm_tis_core.h | 166 +++++++++
>  include/linux/tpm.h             |   4 +
>  6 files changed, 954 insertions(+), 751 deletions(-)
>  create mode 100644 drivers/char/tpm/tpm_tis_core.c
>  create mode 100644 drivers/char/tpm/tpm_tis_core.h
> 
> diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
> index 56e8f1f..c6a4cea 100644
> --- a/drivers/char/tpm/Makefile
> +++ b/drivers/char/tpm/Makefile
> @@ -2,7 +2,7 @@
>  # Makefile for the kernel tpm device drivers.
>  #
>  obj-$(CONFIG_TCG_TPM) += tpm.o
> -tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o
> +tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o tpm_tis_core.o
>  tpm-$(CONFIG_ACPI) += tpm_ppi.o
>  
>  ifdef CONFIG_ACPI
> diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> index 6a973b9..3ec04f4 100644
> --- a/drivers/char/tpm/tpm.h
> +++ b/drivers/char/tpm/tpm.h
> @@ -142,6 +142,7 @@ struct tpm_vendor_specific {
>  
>  	int region_size;
>  	int have_region;
> +	bool itpm;
>  
>  	struct list_head list;
>  	int locality;
> @@ -149,6 +150,7 @@ struct tpm_vendor_specific {
>  	bool timeout_adjusted;
>  	unsigned long duration[3]; /* jiffies */
>  	bool duration_adjusted;
> +	bool irq_tested;
>  	void *priv;
>  
>  	wait_queue_head_t read_queue;
> diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
> index 607fa3f..eb86667 100644
> --- a/drivers/char/tpm/tpm_tis.c
> +++ b/drivers/char/tpm/tpm_tis.c
> @@ -19,6 +19,7 @@
>   * published by the Free Software Foundation, version 2 of the
>   * License.
>   */
> +
>  #include <linux/init.h>
>  #include <linux/module.h>
>  #include <linux/moduleparam.h>
> @@ -29,40 +30,49 @@
>  #include <linux/acpi.h>
>  #include <linux/freezer.h>
>  #include "tpm.h"
> +#include "tpm_tis_core.h"
>  
> -enum tis_access {
> -	TPM_ACCESS_VALID = 0x80,
> -	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
> -	TPM_ACCESS_REQUEST_PENDING = 0x04,
> -	TPM_ACCESS_REQUEST_USE = 0x02,
> -};
> +static int read_mem_bytes(struct tpm_chip *chip, u32 addr, size_t len, u8 size,
> +			  u8 *result)
> +{
> +	int i;
>  
> -enum tis_status {
> -	TPM_STS_VALID = 0x80,
> -	TPM_STS_COMMAND_READY = 0x40,
> -	TPM_STS_GO = 0x20,
> -	TPM_STS_DATA_AVAIL = 0x10,
> -	TPM_STS_DATA_EXPECT = 0x08,
> -};
> +	switch (size) {
> +	case 4:
> +		*(u32 *)result = ioread32(chip->vendor.iobase + addr);
> +	break;
> +	case 2:
> +		*(u16 *)result = ioread16(chip->vendor.iobase + addr);
> +	break;
> +	case 1:
> +	default:
> +		for (i = 0; i < len; i++)
> +			result[i] = ioread8(chip->vendor.iobase + addr);
> +	}
>  
> -enum tis_int_flags {
> -	TPM_GLOBAL_INT_ENABLE = 0x80000000,
> -	TPM_INTF_BURST_COUNT_STATIC = 0x100,
> -	TPM_INTF_CMD_READY_INT = 0x080,
> -	TPM_INTF_INT_EDGE_FALLING = 0x040,
> -	TPM_INTF_INT_EDGE_RISING = 0x020,
> -	TPM_INTF_INT_LEVEL_LOW = 0x010,
> -	TPM_INTF_INT_LEVEL_HIGH = 0x008,
> -	TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
> -	TPM_INTF_STS_VALID_INT = 0x002,
> -	TPM_INTF_DATA_AVAIL_INT = 0x001,
> -};
> +	return 0;
> +}
>  
> -enum tis_defaults {
> -	TIS_MEM_LEN = 0x5000,
> -	TIS_SHORT_TIMEOUT = 750,	/* ms */
> -	TIS_LONG_TIMEOUT = 2000,	/* 2 sec */
> -};
> +static int write_mem_bytes(struct tpm_chip *chip, u32 addr, size_t len, u8 size,
> +			   u8 *value)
> +{
> +	int i;
> +
> +	switch (size) {
> +	case 4:
> +		iowrite32(*(u32 *)value, chip->vendor.iobase + addr);
> +	break;
> +	case 2:
> +		iowrite16(*(u16 *)value, chip->vendor.iobase + addr);
> +	break;
> +	case 1:
> +	default:
> +		for (i = 0 ; i < len; i++)
> +			iowrite8(value[i], chip->vendor.iobase + addr);
> +	}
> +
> +	return 0;
> +}
>  
>  struct tpm_info {
>  	struct resource res;
> @@ -73,38 +83,14 @@ struct tpm_info {
>  	int irq;
>  };
>  
> -/* Some timeout values are needed before it is known whether the chip is
> - * TPM 1.0 or TPM 2.0.
> - */
> -#define TIS_TIMEOUT_A_MAX	max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_A)
> -#define TIS_TIMEOUT_B_MAX	max(TIS_LONG_TIMEOUT, TPM2_TIMEOUT_B)
> -#define TIS_TIMEOUT_C_MAX	max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_C)
> -#define TIS_TIMEOUT_D_MAX	max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_D)
> -
> -#define	TPM_ACCESS(l)			(0x0000 | ((l) << 12))
> -#define	TPM_INT_ENABLE(l)		(0x0008 | ((l) << 12))
> -#define	TPM_INT_VECTOR(l)		(0x000C | ((l) << 12))
> -#define	TPM_INT_STATUS(l)		(0x0010 | ((l) << 12))
> -#define	TPM_INTF_CAPS(l)		(0x0014 | ((l) << 12))
> -#define	TPM_STS(l)			(0x0018 | ((l) << 12))
> -#define	TPM_STS3(l)			(0x001b | ((l) << 12))
> -#define	TPM_DATA_FIFO(l)		(0x0024 | ((l) << 12))
> -
> -#define	TPM_DID_VID(l)			(0x0F00 | ((l) << 12))
> -#define	TPM_RID(l)			(0x0F04 | ((l) << 12))
> -
> -struct priv_data {
> -	bool irq_tested;
> -};
> -
>  #if defined(CONFIG_PNP) && defined(CONFIG_ACPI)
>  static int has_hid(struct acpi_device *dev, const char *hid)
>  {
>  	struct acpi_hardware_id *id;
>  
>  	list_for_each_entry(id, &dev->pnp.ids, list)
> -		if (!strcmp(hid, id->id))
> -			return 1;
> +	if (!strcmp(hid, id->id))
> +		return 1;
>  
>  	return 0;
>  }
> @@ -120,409 +106,10 @@ static inline int is_itpm(struct acpi_device *dev)
>  }
>  #endif
>  
> -/* Before we attempt to access the TPM we must see that the valid bit is set.
> - * The specification says that this bit is 0 at reset and remains 0 until the
> - * 'TPM has gone through its self test and initialization and has established
> - * correct values in the other bits.' */
> -static int wait_startup(struct tpm_chip *chip, int l)
> -{
> -	unsigned long stop = jiffies + chip->vendor.timeout_a;
> -	do {
> -		if (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
> -		    TPM_ACCESS_VALID)
> -			return 0;
> -		msleep(TPM_TIMEOUT);
> -	} while (time_before(jiffies, stop));
> -	return -1;
> -}
> -
> -static int check_locality(struct tpm_chip *chip, int l)
> -{
> -	if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
> -	     (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
> -	    (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
> -		return chip->vendor.locality = l;
> -
> -	return -1;
> -}
> -
> -static void release_locality(struct tpm_chip *chip, int l, int force)
> -{
> -	if (force || (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
> -		      (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
> -	    (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID))
> -		iowrite8(TPM_ACCESS_ACTIVE_LOCALITY,
> -			 chip->vendor.iobase + TPM_ACCESS(l));
> -}
> -
> -static int request_locality(struct tpm_chip *chip, int l)
> -{
> -	unsigned long stop, timeout;
> -	long rc;
> -
> -	if (check_locality(chip, l) >= 0)
> -		return l;
> -
> -	iowrite8(TPM_ACCESS_REQUEST_USE,
> -		 chip->vendor.iobase + TPM_ACCESS(l));
> -
> -	stop = jiffies + chip->vendor.timeout_a;
> -
> -	if (chip->vendor.irq) {
> -again:
> -		timeout = stop - jiffies;
> -		if ((long)timeout <= 0)
> -			return -1;
> -		rc = wait_event_interruptible_timeout(chip->vendor.int_queue,
> -						      (check_locality
> -						       (chip, l) >= 0),
> -						      timeout);
> -		if (rc > 0)
> -			return l;
> -		if (rc == -ERESTARTSYS && freezing(current)) {
> -			clear_thread_flag(TIF_SIGPENDING);
> -			goto again;
> -		}
> -	} else {
> -		/* wait for burstcount */
> -		do {
> -			if (check_locality(chip, l) >= 0)
> -				return l;
> -			msleep(TPM_TIMEOUT);
> -		}
> -		while (time_before(jiffies, stop));
> -	}
> -	return -1;
> -}
> -
> -static u8 tpm_tis_status(struct tpm_chip *chip)
> -{
> -	return ioread8(chip->vendor.iobase +
> -		       TPM_STS(chip->vendor.locality));
> -}
> -
> -static void tpm_tis_ready(struct tpm_chip *chip)
> -{
> -	/* this causes the current command to be aborted */
> -	iowrite8(TPM_STS_COMMAND_READY,
> -		 chip->vendor.iobase + TPM_STS(chip->vendor.locality));
> -}
> -
> -static int get_burstcount(struct tpm_chip *chip)
> -{
> -	unsigned long stop;
> -	int burstcnt;
> -
> -	/* wait for burstcount */
> -	/* which timeout value, spec has 2 answers (c & d) */
> -	stop = jiffies + chip->vendor.timeout_d;
> -	do {
> -		burstcnt = ioread8(chip->vendor.iobase +
> -				   TPM_STS(chip->vendor.locality) + 1);
> -		burstcnt += ioread8(chip->vendor.iobase +
> -				    TPM_STS(chip->vendor.locality) +
> -				    2) << 8;
> -		if (burstcnt)
> -			return burstcnt;
> -		msleep(TPM_TIMEOUT);
> -	} while (time_before(jiffies, stop));
> -	return -EBUSY;
> -}
> -
> -static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
> -{
> -	int size = 0, burstcnt;
> -	while (size < count &&
> -	       wait_for_tpm_stat(chip,
> -				 TPM_STS_DATA_AVAIL | TPM_STS_VALID,
> -				 chip->vendor.timeout_c,
> -				 &chip->vendor.read_queue, true)
> -	       == 0) {
> -		burstcnt = get_burstcount(chip);
> -		for (; burstcnt > 0 && size < count; burstcnt--)
> -			buf[size++] = ioread8(chip->vendor.iobase +
> -					      TPM_DATA_FIFO(chip->vendor.
> -							    locality));
> -	}
> -	return size;
> -}
> -
> -static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
> -{
> -	int size = 0;
> -	int expected, status;
> -
> -	if (count < TPM_HEADER_SIZE) {
> -		size = -EIO;
> -		goto out;
> -	}
> -
> -	/* read first 10 bytes, including tag, paramsize, and result */
> -	if ((size =
> -	     recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) {
> -		dev_err(&chip->dev, "Unable to read header\n");
> -		goto out;
> -	}
> -
> -	expected = be32_to_cpu(*(__be32 *) (buf + 2));
> -	if (expected > count) {
> -		size = -EIO;
> -		goto out;
> -	}
> -
> -	if ((size +=
> -	     recv_data(chip, &buf[TPM_HEADER_SIZE],
> -		       expected - TPM_HEADER_SIZE)) < expected) {
> -		dev_err(&chip->dev, "Unable to read remainder of result\n");
> -		size = -ETIME;
> -		goto out;
> -	}
> -
> -	wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
> -			  &chip->vendor.int_queue, false);
> -	status = tpm_tis_status(chip);
> -	if (status & TPM_STS_DATA_AVAIL) {	/* retry? */
> -		dev_err(&chip->dev, "Error left over data\n");
> -		size = -EIO;
> -		goto out;
> -	}
> -
> -out:
> -	tpm_tis_ready(chip);
> -	release_locality(chip, chip->vendor.locality, 0);
> -	return size;
> -}
> -
>  static bool itpm;
>  module_param(itpm, bool, 0444);
>  MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)");
>  
> -/*
> - * If interrupts are used (signaled by an irq set in the vendor structure)
> - * tpm.c can skip polling for the data to be available as the interrupt is
> - * waited for here
> - */
> -static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
> -{
> -	int rc, status, burstcnt;
> -	size_t count = 0;
> -
> -	if (request_locality(chip, 0) < 0)
> -		return -EBUSY;
> -
> -	status = tpm_tis_status(chip);
> -	if ((status & TPM_STS_COMMAND_READY) == 0) {
> -		tpm_tis_ready(chip);
> -		if (wait_for_tpm_stat
> -		    (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
> -		     &chip->vendor.int_queue, false) < 0) {
> -			rc = -ETIME;
> -			goto out_err;
> -		}
> -	}
> -
> -	while (count < len - 1) {
> -		burstcnt = get_burstcount(chip);
> -		for (; burstcnt > 0 && count < len - 1; burstcnt--) {
> -			iowrite8(buf[count], chip->vendor.iobase +
> -				 TPM_DATA_FIFO(chip->vendor.locality));
> -			count++;
> -		}
> -
> -		wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
> -				  &chip->vendor.int_queue, false);
> -		status = tpm_tis_status(chip);
> -		if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) {
> -			rc = -EIO;
> -			goto out_err;
> -		}
> -	}
> -
> -	/* write last byte */
> -	iowrite8(buf[count],
> -		 chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality));
> -	wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
> -			  &chip->vendor.int_queue, false);
> -	status = tpm_tis_status(chip);
> -	if ((status & TPM_STS_DATA_EXPECT) != 0) {
> -		rc = -EIO;
> -		goto out_err;
> -	}
> -
> -	return 0;
> -
> -out_err:
> -	tpm_tis_ready(chip);
> -	release_locality(chip, chip->vendor.locality, 0);
> -	return rc;
> -}
> -
> -static void disable_interrupts(struct tpm_chip *chip)
> -{
> -	u32 intmask;
> -
> -	intmask =
> -	    ioread32(chip->vendor.iobase +
> -		     TPM_INT_ENABLE(chip->vendor.locality));
> -	intmask &= ~TPM_GLOBAL_INT_ENABLE;
> -	iowrite32(intmask,
> -		  chip->vendor.iobase +
> -		  TPM_INT_ENABLE(chip->vendor.locality));
> -	devm_free_irq(&chip->dev, chip->vendor.irq, chip);
> -	chip->vendor.irq = 0;
> -}
> -
> -/*
> - * If interrupts are used (signaled by an irq set in the vendor structure)
> - * tpm.c can skip polling for the data to be available as the interrupt is
> - * waited for here
> - */
> -static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len)
> -{
> -	int rc;
> -	u32 ordinal;
> -	unsigned long dur;
> -
> -	rc = tpm_tis_send_data(chip, buf, len);
> -	if (rc < 0)
> -		return rc;
> -
> -	/* go and do it */
> -	iowrite8(TPM_STS_GO,
> -		 chip->vendor.iobase + TPM_STS(chip->vendor.locality));
> -
> -	if (chip->vendor.irq) {
> -		ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
> -
> -		if (chip->flags & TPM_CHIP_FLAG_TPM2)
> -			dur = tpm2_calc_ordinal_duration(chip, ordinal);
> -		else
> -			dur = tpm_calc_ordinal_duration(chip, ordinal);
> -
> -		if (wait_for_tpm_stat
> -		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,
> -		     &chip->vendor.read_queue, false) < 0) {
> -			rc = -ETIME;
> -			goto out_err;
> -		}
> -	}
> -	return len;
> -out_err:
> -	tpm_tis_ready(chip);
> -	release_locality(chip, chip->vendor.locality, 0);
> -	return rc;
> -}
> -
> -static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
> -{
> -	int rc, irq;
> -	struct priv_data *priv = chip->vendor.priv;
> -
> -	if (!chip->vendor.irq || priv->irq_tested)
> -		return tpm_tis_send_main(chip, buf, len);
> -
> -	/* Verify receipt of the expected IRQ */
> -	irq = chip->vendor.irq;
> -	chip->vendor.irq = 0;
> -	rc = tpm_tis_send_main(chip, buf, len);
> -	chip->vendor.irq = irq;
> -	if (!priv->irq_tested)
> -		msleep(1);
> -	if (!priv->irq_tested)
> -		disable_interrupts(chip);
> -	priv->irq_tested = true;
> -	return rc;
> -}
> -
> -struct tis_vendor_timeout_override {
> -	u32 did_vid;
> -	unsigned long timeout_us[4];
> -};
> -
> -static const struct tis_vendor_timeout_override vendor_timeout_overrides[] = {
> -	/* Atmel 3204 */
> -	{ 0x32041114, { (TIS_SHORT_TIMEOUT*1000), (TIS_LONG_TIMEOUT*1000),
> -			(TIS_SHORT_TIMEOUT*1000), (TIS_SHORT_TIMEOUT*1000) } },
> -};
> -
> -static bool tpm_tis_update_timeouts(struct tpm_chip *chip,
> -				    unsigned long *timeout_cap)
> -{
> -	int i;
> -	u32 did_vid;
> -
> -	did_vid = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
> -
> -	for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) {
> -		if (vendor_timeout_overrides[i].did_vid != did_vid)
> -			continue;
> -		memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us,
> -		       sizeof(vendor_timeout_overrides[i].timeout_us));
> -		return true;
> -	}
> -
> -	return false;
> -}
> -
> -/*
> - * Early probing for iTPM with STS_DATA_EXPECT flaw.
> - * Try sending command without itpm flag set and if that
> - * fails, repeat with itpm flag set.
> - */
> -static int probe_itpm(struct tpm_chip *chip)
> -{
> -	int rc = 0;
> -	u8 cmd_getticks[] = {
> -		0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a,
> -		0x00, 0x00, 0x00, 0xf1
> -	};
> -	size_t len = sizeof(cmd_getticks);
> -	bool rem_itpm = itpm;
> -	u16 vendor = ioread16(chip->vendor.iobase + TPM_DID_VID(0));
> -
> -	/* probe only iTPMS */
> -	if (vendor != TPM_VID_INTEL)
> -		return 0;
> -
> -	itpm = false;
> -
> -	rc = tpm_tis_send_data(chip, cmd_getticks, len);
> -	if (rc == 0)
> -		goto out;
> -
> -	tpm_tis_ready(chip);
> -	release_locality(chip, chip->vendor.locality, 0);
> -
> -	itpm = true;
> -
> -	rc = tpm_tis_send_data(chip, cmd_getticks, len);
> -	if (rc == 0) {
> -		dev_info(&chip->dev, "Detected an iTPM.\n");
> -		rc = 1;
> -	} else
> -		rc = -EFAULT;
> -
> -out:
> -	itpm = rem_itpm;
> -	tpm_tis_ready(chip);
> -	release_locality(chip, chip->vendor.locality, 0);
> -
> -	return rc;
> -}
> -
> -static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status)
> -{
> -	switch (chip->vendor.manufacturer_id) {
> -	case TPM_VID_WINBOND:
> -		return ((status == TPM_STS_VALID) ||
> -			(status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)));
> -	case TPM_VID_STM:
> -		return (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY));
> -	default:
> -		return (status == TPM_STS_COMMAND_READY);
> -	}
> -}
> -
>  static const struct tpm_class_ops tpm_tis = {
>  	.status = tpm_tis_status,
>  	.recv = tpm_tis_recv,
> @@ -532,153 +119,24 @@ static const struct tpm_class_ops tpm_tis = {
>  	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
>  	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
>  	.req_canceled = tpm_tis_req_canceled,
> +	.read_bytes = read_mem_bytes,
> +	.write_bytes = write_mem_bytes,
>  };
>  
> -static irqreturn_t tis_int_handler(int dummy, void *dev_id)
> -{
> -	struct tpm_chip *chip = dev_id;
> -	u32 interrupt;
> -	int i;
> -
> -	interrupt = ioread32(chip->vendor.iobase +
> -			     TPM_INT_STATUS(chip->vendor.locality));
> -
> -	if (interrupt == 0)
> -		return IRQ_NONE;
> -
> -	((struct priv_data *)chip->vendor.priv)->irq_tested = true;
> -	if (interrupt & TPM_INTF_DATA_AVAIL_INT)
> -		wake_up_interruptible(&chip->vendor.read_queue);
> -	if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
> -		for (i = 0; i < 5; i++)
> -			if (check_locality(chip, i) >= 0)
> -				break;
> -	if (interrupt &
> -	    (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT |
> -	     TPM_INTF_CMD_READY_INT))
> -		wake_up_interruptible(&chip->vendor.int_queue);
> -
> -	/* Clear interrupts handled with TPM_EOI */
> -	iowrite32(interrupt,
> -		  chip->vendor.iobase +
> -		  TPM_INT_STATUS(chip->vendor.locality));
> -	ioread32(chip->vendor.iobase + TPM_INT_STATUS(chip->vendor.locality));
> -	return IRQ_HANDLED;
> -}
> -
> -/* Register the IRQ and issue a command that will cause an interrupt. If an
> - * irq is seen then leave the chip setup for IRQ operation, otherwise reverse
> - * everything and leave in polling mode. Returns 0 on success.
> - */
> -static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
> -				    int flags, int irq)
> -{
> -	struct priv_data *priv = chip->vendor.priv;
> -	u8 original_int_vec;
> -
> -	if (devm_request_irq(&chip->dev, irq, tis_int_handler, flags,
> -			     dev_name(&chip->dev), chip) != 0) {
> -		dev_info(&chip->dev, "Unable to request irq: %d for probe\n",
> -			 irq);
> -		return -1;
> -	}
> -	chip->vendor.irq = irq;
> -
> -	original_int_vec = ioread8(chip->vendor.iobase +
> -				   TPM_INT_VECTOR(chip->vendor.locality));
> -	iowrite8(irq,
> -		 chip->vendor.iobase + TPM_INT_VECTOR(chip->vendor.locality));
> -
> -	/* Clear all existing */
> -	iowrite32(ioread32(chip->vendor.iobase +
> -			   TPM_INT_STATUS(chip->vendor.locality)),
> -		  chip->vendor.iobase + TPM_INT_STATUS(chip->vendor.locality));
> -
> -	/* Turn on */
> -	iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
> -		  chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality));
> -
> -	priv->irq_tested = false;
> -
> -	/* Generate an interrupt by having the core call through to
> -	 * tpm_tis_send
> -	 */
> -	if (chip->flags & TPM_CHIP_FLAG_TPM2)
> -		tpm2_gen_interrupt(chip);
> -	else
> -		tpm_gen_interrupt(chip);
> -
> -	/* tpm_tis_send will either confirm the interrupt is working or it
> -	 * will call disable_irq which undoes all of the above.
> -	 */
> -	if (!chip->vendor.irq) {
> -		iowrite8(original_int_vec,
> -			 chip->vendor.iobase +
> -			     TPM_INT_VECTOR(chip->vendor.locality));
> -		return 1;
> -	}
> -
> -	return 0;
> -}
> -
> -/* Try to find the IRQ the TPM is using. This is for legacy x86 systems that
> - * do not have ACPI/etc. We typically expect the interrupt to be declared if
> - * present.
> - */
> -static void tpm_tis_probe_irq(struct tpm_chip *chip, u32 intmask)
> -{
> -	u8 original_int_vec;
> -	int i;
> -
> -	original_int_vec = ioread8(chip->vendor.iobase +
> -				   TPM_INT_VECTOR(chip->vendor.locality));
> -
> -	if (!original_int_vec) {
> -		if (IS_ENABLED(CONFIG_X86))
> -			for (i = 3; i <= 15; i++)
> -				if (!tpm_tis_probe_irq_single(chip, intmask, 0,
> -							      i))
> -					return;
> -	} else if (!tpm_tis_probe_irq_single(chip, intmask, 0,
> -					     original_int_vec))
> -		return;
> -}
> -
>  static bool interrupts = true;
>  module_param(interrupts, bool, 0444);
>  MODULE_PARM_DESC(interrupts, "Enable interrupts");
>  
> -static void tpm_tis_remove(struct tpm_chip *chip)
> -{
> -	if (chip->flags & TPM_CHIP_FLAG_TPM2)
> -		tpm2_shutdown(chip, TPM2_SU_CLEAR);
> -
> -	iowrite32(~TPM_GLOBAL_INT_ENABLE &
> -		  ioread32(chip->vendor.iobase +
> -			   TPM_INT_ENABLE(chip->vendor.
> -					  locality)),
> -		  chip->vendor.iobase +
> -		  TPM_INT_ENABLE(chip->vendor.locality));
> -	release_locality(chip, chip->vendor.locality, 1);
> -}
> -
>  static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
>  			acpi_handle acpi_dev_handle)
>  {
> -	u32 vendor, intfcaps, intmask;
> -	int rc, probe;
> +	int ret, irq = tpm_info->irq;
>  	struct tpm_chip *chip;
> -	struct priv_data *priv;
> -
> -	priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL);
> -	if (priv == NULL)
> -		return -ENOMEM;
>  
>  	chip = tpmm_chip_alloc(dev, &tpm_tis);
>  	if (IS_ERR(chip))
>  		return PTR_ERR(chip);
>  
> -	tpm_set_vendordata(chip, priv);
>  #ifdef CONFIG_ACPI
>  	chip->acpi_dev_handle = acpi_dev_handle;
>  #endif
> @@ -687,177 +145,22 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
>  	if (IS_ERR(chip->vendor.iobase))
>  		return PTR_ERR(chip->vendor.iobase);
>  
> -	/* Maximum timeouts */
> -	chip->vendor.timeout_a = TIS_TIMEOUT_A_MAX;
> -	chip->vendor.timeout_b = TIS_TIMEOUT_B_MAX;
> -	chip->vendor.timeout_c = TIS_TIMEOUT_C_MAX;
> -	chip->vendor.timeout_d = TIS_TIMEOUT_D_MAX;
> -
> -	if (wait_startup(chip, 0) != 0) {
> -		rc = -ENODEV;
> -		goto out_err;
> -	}
> +	chip->vendor.itpm = itpm;
>  
> -	/* Take control of the TPM's interrupt hardware and shut it off */
> -	intmask = ioread32(chip->vendor.iobase +
> -			   TPM_INT_ENABLE(chip->vendor.locality));
> -	intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
> -		   TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
> -	intmask &= ~TPM_GLOBAL_INT_ENABLE;
> -	iowrite32(intmask,
> -		  chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality));
> -
> -	if (request_locality(chip, 0) != 0) {
> -		rc = -ENODEV;
> -		goto out_err;
> -	}
> +	if (!interrupts)
> +		irq = -1;
>  
> -	rc = tpm2_probe(chip);
> -	if (rc)
> +	ret = tpm_tis_init_core(dev, chip, irq, IRQF_SHARED);
> +	if (ret < 0)
>  		goto out_err;
>  
> -	vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
> -	chip->vendor.manufacturer_id = vendor;
> -
> -	dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n",
> -		 (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2",
> -		 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
> -
> -	if (!itpm) {
> -		probe = probe_itpm(chip);
> -		if (probe < 0) {
> -			rc = -ENODEV;
> -			goto out_err;
> -		}
> -		itpm = !!probe;
> -	}
> -
> -	if (itpm)
> -		dev_info(dev, "Intel iTPM workaround enabled\n");
> -
> -
> -	/* Figure out the capabilities */
> -	intfcaps =
> -	    ioread32(chip->vendor.iobase +
> -		     TPM_INTF_CAPS(chip->vendor.locality));
> -	dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
> -		intfcaps);
> -	if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
> -		dev_dbg(dev, "\tBurst Count Static\n");
> -	if (intfcaps & TPM_INTF_CMD_READY_INT)
> -		dev_dbg(dev, "\tCommand Ready Int Support\n");
> -	if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
> -		dev_dbg(dev, "\tInterrupt Edge Falling\n");
> -	if (intfcaps & TPM_INTF_INT_EDGE_RISING)
> -		dev_dbg(dev, "\tInterrupt Edge Rising\n");
> -	if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
> -		dev_dbg(dev, "\tInterrupt Level Low\n");
> -	if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
> -		dev_dbg(dev, "\tInterrupt Level High\n");
> -	if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
> -		dev_dbg(dev, "\tLocality Change Int Support\n");
> -	if (intfcaps & TPM_INTF_STS_VALID_INT)
> -		dev_dbg(dev, "\tSts Valid Int Support\n");
> -	if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
> -		dev_dbg(dev, "\tData Avail Int Support\n");
> -
> -	/* Very early on issue a command to the TPM in polling mode to make
> -	 * sure it works. May as well use that command to set the proper
> -	 *  timeouts for the driver.
> -	 */
> -	if (tpm_get_timeouts(chip)) {
> -		dev_err(dev, "Could not get TPM timeouts and durations\n");
> -		rc = -ENODEV;
> -		goto out_err;
> -	}
> +	return ret;
>  
> -	/* INTERRUPT Setup */
> -	init_waitqueue_head(&chip->vendor.read_queue);
> -	init_waitqueue_head(&chip->vendor.int_queue);
> -	if (interrupts && tpm_info->irq != -1) {
> -		if (tpm_info->irq) {
> -			tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
> -						 tpm_info->irq);
> -			if (!chip->vendor.irq)
> -				dev_err(&chip->dev, FW_BUG
> -					"TPM interrupt not working, polling instead\n");
> -		} else
> -			tpm_tis_probe_irq(chip, intmask);
> -	}
> -
> -	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
> -		rc = tpm2_do_selftest(chip);
> -		if (rc == TPM2_RC_INITIALIZE) {
> -			dev_warn(dev, "Firmware has not started TPM\n");
> -			rc  = tpm2_startup(chip, TPM2_SU_CLEAR);
> -			if (!rc)
> -				rc = tpm2_do_selftest(chip);
> -		}
> -
> -		if (rc) {
> -			dev_err(dev, "TPM self test failed\n");
> -			if (rc > 0)
> -				rc = -ENODEV;
> -			goto out_err;
> -		}
> -	} else {
> -		if (tpm_do_selftest(chip)) {
> -			dev_err(dev, "TPM self test failed\n");
> -			rc = -ENODEV;
> -			goto out_err;
> -		}
> -	}
> -
> -	return tpm_chip_register(chip);
>  out_err:
>  	tpm_tis_remove(chip);
> -	return rc;
> -}
> -
> -#ifdef CONFIG_PM_SLEEP
> -static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
> -{
> -	u32 intmask;
> -
> -	/* reenable interrupts that device may have lost or
> -	   BIOS/firmware may have disabled */
> -	iowrite8(chip->vendor.irq, chip->vendor.iobase +
> -		 TPM_INT_VECTOR(chip->vendor.locality));
> -
> -	intmask =
> -	    ioread32(chip->vendor.iobase +
> -		     TPM_INT_ENABLE(chip->vendor.locality));
> -
> -	intmask |= TPM_INTF_CMD_READY_INT
> -	    | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
> -	    | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE;
> -
> -	iowrite32(intmask,
> -		  chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality));
> +	return ret;
>  }
>  
> -static int tpm_tis_resume(struct device *dev)
> -{
> -	struct tpm_chip *chip = dev_get_drvdata(dev);
> -	int ret;
> -
> -	if (chip->vendor.irq)
> -		tpm_tis_reenable_interrupts(chip);
> -
> -	ret = tpm_pm_resume(dev);
> -	if (ret)
> -		return ret;
> -
> -	/* TPM 1.2 requires self-test on resume. This function actually returns
> -	 * an error code but for unknown reason it isn't handled.
> -	 */
> -	if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
> -		tpm_do_selftest(chip);
> -
> -	return 0;
> -}
> -#endif
> -
>  static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume);
>  
>  static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
> @@ -919,7 +222,7 @@ static struct pnp_driver tis_pnp_driver = {
>  	},
>  };
>  
> -#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2
> +#define TIS_HID_USR_IDX (sizeof(tpm_pnp_tbl) / sizeof(struct pnp_device_id) - 2)
>  module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
>  		    sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
>  MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
> diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
> new file mode 100644
> index 0000000..b9cc61f
> --- /dev/null
> +++ b/drivers/char/tpm/tpm_tis_core.c
> @@ -0,0 +1,728 @@
> +/*
> + * Copyright (C) 2005, 2006 IBM Corporation
> + * Copyright (C) 2014, 2015 Intel Corporation
> + *
> + * Authors:
> + * Leendert van Doorn <leendert-aZOuKsOsJu3MbYB6QlFGEg@public.gmane.org>
> + * Kylene Hall <kjhall-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> + *
> + * Maintained by: <tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
> + *
> + * Device driver for TCG/TCPA TPM (trusted platform module).
> + * Specifications at www.trustedcomputinggroup.org
> + *
> + * This device driver implements the TPM interface as defined in
> + * the TCG TPM Interface Spec version 1.2, revision 1.0.
> + *
> + * 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 the Free Software Foundation, version 2 of the
> + * License.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/moduleparam.h>
> +#include <linux/pnp.h>
> +#include <linux/slab.h>
> +#include <linux/interrupt.h>
> +#include <linux/wait.h>
> +#include <linux/acpi.h>
> +#include <linux/freezer.h>
> +#include "tpm.h"
> +#include "tpm_tis_core.h"
> +
> +struct tpm_info {
> +	struct resource res;
> +	/* irq > 0 means: use irq $irq;
> +	 * irq = 0 means: autoprobe for an irq;
> +	 * irq = -1 means: no irq support
> +	 */
> +	int irq;
> +};
> +
> +/* Before we attempt to access the TPM we must see that the valid bit is set.
> + * The specification says that this bit is 0 at reset and remains 0 until the
> + * 'TPM has gone through its self test and initialization and has established
> + * correct values in the other bits.'
> + */
> +static int wait_startup(struct tpm_chip *chip, int l)
> +{
> +	unsigned long stop = jiffies + chip->vendor.timeout_a;
> +
> +	do {
> +		if (tpm_read_byte(chip, TPM_ACCESS(l)) & TPM_ACCESS_VALID)
> +			return 0;
> +		msleep(TPM_TIMEOUT);
> +	} while (time_before(jiffies, stop));
> +	return -1;
> +}
> +
> +static int check_locality(struct tpm_chip *chip, int l)
> +{
> +	if ((tpm_read_byte(chip, TPM_ACCESS(l)) &
> +	     (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
> +	    (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
> +		return chip->vendor.locality = l;
> +
> +	return -1;
> +}
> +
> +static void release_locality(struct tpm_chip *chip, int l, int force)
> +{
> +	if (force || (tpm_read_byte(chip, TPM_ACCESS(l)) &
> +		      (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
> +	    (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID))
> +		tpm_write_byte(chip, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
> +}
> +
> +static int request_locality(struct tpm_chip *chip, int l)
> +{
> +	unsigned long stop, timeout;
> +	long rc;
> +
> +	if (check_locality(chip, l) >= 0)
> +		return l;
> +
> +	tpm_write_byte(chip, TPM_ACCESS(l), TPM_ACCESS_REQUEST_USE);
> +
> +	stop = jiffies + chip->vendor.timeout_a;
> +
> +	if (chip->vendor.irq) {
> +again:
> +		timeout = stop - jiffies;
> +		if ((long)timeout <= 0)
> +			return -1;
> +		rc = wait_event_interruptible_timeout(chip->vendor.int_queue,
> +						      (check_locality
> +						       (chip, l) >= 0),
> +						      timeout);
> +		if (rc > 0)
> +			return l;
> +		if (rc == -ERESTARTSYS && freezing(current)) {
> +			clear_thread_flag(TIF_SIGPENDING);
> +			goto again;
> +		}
> +	} else {
> +		/* wait for burstcount */
> +		do {
> +			if (check_locality(chip, l) >= 0)
> +				return l;
> +			msleep(TPM_TIMEOUT);
> +		} while (time_before(jiffies, stop));
> +	}
> +	return -1;
> +}
> +
> +u8 tpm_tis_status(struct tpm_chip *chip)
> +{
> +	return tpm_read_byte(chip, TPM_STS(chip->vendor.locality));
> +}
> +EXPORT_SYMBOL(tpm_tis_status);
> +
> +void tpm_tis_ready(struct tpm_chip *chip)
> +{
> +	/* this causes the current command to be aborted */
> +	tpm_write_byte(chip, TPM_STS(chip->vendor.locality),
> +		       TPM_STS_COMMAND_READY);
> +}
> +EXPORT_SYMBOL(tpm_tis_ready);
> +
> +static int get_burstcount(struct tpm_chip *chip)
> +{
> +	unsigned long stop;
> +	int burstcnt, status;
> +	u8 temp;
> +
> +	/* wait for burstcount */
> +	/* which timeout value, spec has 2 answers (c & d) */
> +	stop = jiffies + chip->vendor.timeout_d;
> +	do {
> +		status = tpm_read_bytes(chip, TPM_STS(chip->vendor.locality) +
> +					1, 1, &temp);
> +		if (status < 0)
> +			return -EBUSY;
> +
> +		burstcnt = temp;
> +		status = tpm_read_bytes(chip, TPM_STS(chip->vendor.locality) +
> +					2, 1, &temp);
> +		if (status < 0)
> +			return -EBUSY;
> +
> +		burstcnt |= temp << 8;
> +
> +		if (burstcnt)
> +			return burstcnt;
> +		msleep(TPM_TIMEOUT);
> +	} while (time_before(jiffies, stop));
> +	return -EBUSY;
> +}
> +
> +static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
> +{
> +	int size = 0, burstcnt, transfer_size, ret;
> +
> +	while (size < count &&
> +		wait_for_tpm_stat(chip,
> +				 TPM_STS_DATA_AVAIL | TPM_STS_VALID,
> +				 chip->vendor.timeout_c,
> +				 &chip->vendor.read_queue, true) == 0) {
> +		burstcnt = get_burstcount(chip);
> +
> +		transfer_size = min_t(size_t, (count - size), burstcnt);
> +
> +		ret = tpm_read_bytes(chip, TPM_DATA_FIFO(chip->vendor.locality),
> +				     transfer_size, &buf[size]);
> +		if (ret < 0)
> +			return ret;
> +
> +		size += transfer_size;
> +	}
> +
> +	return size;
> +}
> +
> +int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
> +{
> +	int size = 0;
> +	int expected, status;
> +
> +	if (count < TPM_HEADER_SIZE) {
> +		size = -EIO;
> +		goto out;
> +	}
> +
> +	/* read first 10 bytes, including tag, paramsize, and result */
> +	size = recv_data(chip, buf, TPM_HEADER_SIZE);
> +	if (size < TPM_HEADER_SIZE) {
> +		dev_err(&chip->dev, "Unable to read header\n");
> +		goto out;
> +	}
> +
> +	expected = be32_to_cpu(*(__be32 *) (buf + 2));
> +	if (expected > count) {
> +		size = -EIO;
> +		goto out;
> +	}
> +
> +	size += recv_data(chip, &buf[TPM_HEADER_SIZE],
> +			  expected - TPM_HEADER_SIZE);
> +	if (size < expected) {
> +		dev_err(&chip->dev, "Unable to read remainder of result\n");
> +		size = -ETIME;
> +		goto out;
> +	}
> +
> +	wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
> +			  &chip->vendor.int_queue, false);
> +	status = tpm_tis_status(chip);
> +	if (status & TPM_STS_DATA_AVAIL) {	/* retry? */
> +		dev_err(&chip->dev, "Error left over data\n");
> +		size = -EIO;
> +		goto out;
> +	}
> +
> +out:
> +	tpm_tis_ready(chip);
> +	release_locality(chip, chip->vendor.locality, 0);
> +	return size;
> +}
> +EXPORT_SYMBOL(tpm_tis_recv);
> +
> +/*
> + * If interrupts are used (signaled by an irq set in the vendor structure)
> + * tpm.c can skip polling for the data to be available as the interrupt is
> + * waited for here
> + */
> +static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
> +{
> +	int rc, status, burstcnt, transfer_size;
> +	size_t count = 0;
> +
> +	if (request_locality(chip, 0) < 0)
> +		return -EBUSY;
> +
> +	status = tpm_tis_status(chip);
> +	if ((status & TPM_STS_COMMAND_READY) == 0) {
> +		tpm_tis_ready(chip);
> +		if (wait_for_tpm_stat
> +		    (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
> +		     &chip->vendor.int_queue, false) < 0) {
> +			rc = -ETIME;
> +			goto out_err;
> +		}
> +	}
> +
> +	while (count < len - 1) {
> +		burstcnt = get_burstcount(chip);
> +		transfer_size = min_t(size_t, len - count - 1, burstcnt);
> +
> +		rc = tpm_write_bytes(chip, TPM_DATA_FIFO(chip->vendor.locality),
> +				     transfer_size, &buf[count]);
> +		if (rc < 0)
> +			goto out_err;
> +
> +		count += transfer_size;
> +
> +		wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
> +				  &chip->vendor.int_queue, false);
> +		status = tpm_tis_status(chip);
> +		if (!chip->vendor.itpm && (status & TPM_STS_DATA_EXPECT) == 0) {
> +			rc = -EIO;
> +			goto out_err;
> +		}
> +	}
> +
> +	/* write last byte */
> +	tpm_write_byte(chip, TPM_DATA_FIFO(chip->vendor.locality), buf[count]);
> +	wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
> +			  &chip->vendor.int_queue, false);
> +	status = tpm_tis_status(chip);
> +	if ((status & TPM_STS_DATA_EXPECT) != 0) {
> +		rc = -EIO;
> +		goto out_err;
> +	}
> +
> +	return 0;
> +
> +out_err:
> +	tpm_tis_ready(chip);
> +	release_locality(chip, chip->vendor.locality, 0);
> +	return rc;
> +}
> +
> +static void disable_interrupts(struct tpm_chip *chip)
> +{
> +	u32 intmask;
> +
> +	intmask = tpm_read_dword(chip, TPM_INT_ENABLE(chip->vendor.locality));
> +	intmask &= ~TPM_GLOBAL_INT_ENABLE;
> +	tpm_write_dword(chip, TPM_INT_ENABLE(chip->vendor.locality), intmask);
> +	devm_free_irq(&chip->dev, chip->vendor.irq, chip);
> +	chip->vendor.irq = 0;
> +}
> +
> +/*
> + * If interrupts are used (signaled by an irq set in the vendor structure)
> + * tpm.c can skip polling for the data to be available as the interrupt is
> + * waited for here
> + */
> +static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len)
> +{
> +	int rc;
> +	u32 ordinal;
> +	unsigned long dur;
> +
> +	rc = tpm_tis_send_data(chip, buf, len);
> +	if (rc < 0)
> +		return rc;
> +
> +	/* go and do it */
> +	tpm_write_byte(chip, TPM_STS(chip->vendor.locality), TPM_STS_GO);
> +
> +	if (chip->vendor.irq) {
> +		ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
> +
> +		if (chip->flags & TPM_CHIP_FLAG_TPM2)
> +			dur = tpm2_calc_ordinal_duration(chip, ordinal);
> +		else
> +			dur = tpm_calc_ordinal_duration(chip, ordinal);
> +
> +		if (wait_for_tpm_stat
> +		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,
> +		     &chip->vendor.read_queue, false) < 0) {
> +			rc = -ETIME;
> +			goto out_err;
> +		}
> +	}
> +	return len;
> +out_err:
> +	tpm_tis_ready(chip);
> +	release_locality(chip, chip->vendor.locality, 0);
> +	return rc;
> +}
> +
> +int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
> +{
> +	int rc, irq;
> +
> +	if (!chip->vendor.irq || chip->vendor.irq_tested)
> +		return tpm_tis_send_main(chip, buf, len);
> +
> +	/* Verify receipt of the expected IRQ */
> +	irq = chip->vendor.irq;
> +	chip->vendor.irq = 0;
> +	rc = tpm_tis_send_main(chip, buf, len);
> +	chip->vendor.irq = irq;
> +	if (!chip->vendor.irq_tested)
> +		msleep(1);
> +	if (!chip->vendor.irq_tested)
> +		disable_interrupts(chip);
> +	chip->vendor.irq_tested = true;
> +	return rc;
> +}
> +EXPORT_SYMBOL(tpm_tis_send);
> +
> +bool tpm_tis_update_timeouts(struct tpm_chip *chip, unsigned long *timeout_cap)
> +{
> +	int i;
> +	u32 did_vid;
> +
> +	did_vid = tpm_read_dword(chip, TPM_DID_VID(0));
> +
> +	for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) {
> +		if (vendor_timeout_overrides[i].did_vid != did_vid)
> +			continue;
> +		memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us,
> +		       sizeof(vendor_timeout_overrides[i].timeout_us));
> +		return true;
> +	}
> +
> +	return false;
> +}
> +EXPORT_SYMBOL(tpm_tis_update_timeouts);
> +
> +/*
> + * Early probing for iTPM with STS_DATA_EXPECT flaw.
> + * Try sending command without itpm flag set and if that
> + * fails, repeat with itpm flag set.
> + */
> +static int probe_itpm(struct tpm_chip *chip)
> +{
> +	int rc = 0;
> +	u8 cmd_getticks[] = {
> +		0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a,
> +		0x00, 0x00, 0x00, 0xf1
> +	};
> +	size_t len = sizeof(cmd_getticks);
> +	bool rem_itpm = chip->vendor.itpm;
> +	u16 vendor = tpm_read_word(chip, TPM_DID_VID(0));
> +
> +	/* probe only iTPMS */
> +	if (vendor != TPM_VID_INTEL)
> +		return 0;
> +
> +	chip->vendor.itpm = false;
> +
> +	rc = tpm_tis_send_data(chip, cmd_getticks, len);
> +	if (rc == 0)
> +		goto out;
> +
> +	tpm_tis_ready(chip);
> +	release_locality(chip, chip->vendor.locality, 0);
> +
> +	chip->vendor.itpm = true;
> +
> +	rc = tpm_tis_send_data(chip, cmd_getticks, len);
> +	if (rc == 0) {
> +		dev_info(&chip->dev, "Detected an iTPM.\n");
> +		rc = 1;
> +	} else {
> +		rc = -EFAULT;
> +	}
> +
> +out:
> +	chip->vendor.itpm = rem_itpm;
> +	tpm_tis_ready(chip);
> +	release_locality(chip, chip->vendor.locality, 0);
> +
> +	return rc;
> +}
> +
> +bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status)
> +{
> +	switch (chip->vendor.manufacturer_id) {
> +	case TPM_VID_WINBOND:
> +		return ((status == TPM_STS_VALID) ||
> +			(status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)));
> +	case TPM_VID_STM:
> +		return (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY));
> +	default:
> +		return (status == TPM_STS_COMMAND_READY);
> +	}
> +}
> +EXPORT_SYMBOL(tpm_tis_req_canceled);
> +
> +static irqreturn_t tis_int_handler(int dummy, void *dev_id)
> +{
> +	struct tpm_chip *chip = dev_id;
> +	u32 interrupt;
> +	int i;
> +
> +	interrupt = tpm_read_dword(chip, TPM_INT_STATUS(chip->vendor.locality));
> +
> +	if (interrupt == 0)
> +		return IRQ_NONE;
> +
> +	chip->vendor.irq_tested = true;
> +	if (interrupt & TPM_INTF_DATA_AVAIL_INT)
> +		wake_up_interruptible(&chip->vendor.read_queue);
> +	if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
> +		for (i = 0; i < 5; i++)
> +			if (check_locality(chip, i) >= 0)
> +				break;
> +	if (interrupt &
> +	    (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT |
> +	     TPM_INTF_CMD_READY_INT))
> +		wake_up_interruptible(&chip->vendor.int_queue);
> +
> +	/* Clear interrupts handled with TPM_EOI */
> +	tpm_write_dword(chip, TPM_INT_STATUS(chip->vendor.locality), interrupt);
> +	tpm_read_dword(chip, TPM_INT_STATUS(chip->vendor.locality));
> +	return IRQ_HANDLED;
> +}
> +
> +/* Register the IRQ and issue a command that will cause an interrupt. If an
> + * irq is seen then leave the chip setup for IRQ operation, otherwise reverse
> + * everything and leave in polling mode. Returns 0 on success.
> + */
> +static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
> +				    int flags, int irq)
> +{
> +	u8 original_int_vec;
> +
> +	if (devm_request_irq(&chip->dev, irq, tis_int_handler, flags,
> +			     dev_name(&chip->dev), chip) != 0) {
> +		dev_info(&chip->dev, "Unable to request irq: %d for probe\n",
> +			 irq);
> +		return -1;
> +	}
> +	chip->vendor.irq = irq;
> +
> +	original_int_vec = tpm_read_byte(chip, TPM_INT_VECTOR(chip->vendor.locality));
> +	tpm_write_byte(chip, TPM_INT_VECTOR(chip->vendor.locality), irq);
> +
> +	/* Clear all existing */
> +	tpm_write_dword(chip, TPM_INT_STATUS(chip->vendor.locality),
> +			tpm_read_dword(chip, TPM_INT_STATUS(chip->vendor.locality)));
> +
> +	/* Turn on */
> +	tpm_write_dword(chip, TPM_INT_ENABLE(chip->vendor.locality),
> +			intmask | TPM_GLOBAL_INT_ENABLE);
> +
> +	chip->vendor.irq_tested = false;
> +
> +	/* Generate an interrupt by having the core call through to
> +	 * tpm_tis_send
> +	 */
> +	if (chip->flags & TPM_CHIP_FLAG_TPM2)
> +		tpm2_gen_interrupt(chip);
> +	else
> +		tpm_gen_interrupt(chip);
> +
> +	/* tpm_tis_send will either confirm the interrupt is working or it
> +	 * will call disable_irq which undoes all of the above.
> +	 */
> +	if (!chip->vendor.irq) {
> +		tpm_write_byte(chip, TPM_INT_VECTOR(chip->vendor.locality),
> +			       original_int_vec);
> +		return 1;
> +	}
> +
> +	return 0;
> +}
> +
> +/* Try to find the IRQ the TPM is using. This is for legacy x86 systems that
> + * do not have ACPI/etc. We typically expect the interrupt to be declared if
> + * present.
> + */
> +static void tpm_tis_probe_irq(struct tpm_chip *chip, u32 intmask)
> +{
> +	u8 original_int_vec;
> +	int i;
> +
> +	original_int_vec = tpm_read_byte(chip,
> +					 TPM_INT_VECTOR(chip->vendor.locality));
> +
> +	if (!original_int_vec) {
> +		if (IS_ENABLED(CONFIG_X86))
> +			for (i = 3; i <= 15; i++)
> +				if (!tpm_tis_probe_irq_single(chip, intmask, 0,
> +							      i))
> +					return;
> +	} else if (!tpm_tis_probe_irq_single(chip, intmask, 0,
> +					     original_int_vec))
> +		return;
> +}
> +
> +void tpm_tis_remove(struct tpm_chip *chip)
> +{
> +	if (chip->flags & TPM_CHIP_FLAG_TPM2)
> +		tpm2_shutdown(chip, TPM2_SU_CLEAR);
> +
> +	tpm_write_dword(chip, TPM_INT_ENABLE(chip->vendor.locality),
> +			~TPM_GLOBAL_INT_ENABLE &
> +			tpm_read_dword(chip,
> +				       TPM_INT_ENABLE(chip->vendor.locality)));
> +	release_locality(chip, chip->vendor.locality, 1);
> +}
> +EXPORT_SYMBOL(tpm_tis_remove);
> +
> +int tpm_tis_init_core(struct device *dev, struct tpm_chip *chip,
> +		      int irq, int irq_flags)
> +{
> +	u32 vendor, intfcaps, intmask;
> +	int rc, probe;
> +
> +	/* Maximum timeouts */
> +	chip->vendor.timeout_a = TIS_TIMEOUT_A_MAX;
> +	chip->vendor.timeout_b = TIS_TIMEOUT_B_MAX;
> +	chip->vendor.timeout_c = TIS_TIMEOUT_C_MAX;
> +	chip->vendor.timeout_d = TIS_TIMEOUT_D_MAX;
> +
> +	if (wait_startup(chip, 0) != 0) {
> +		rc = -ENODEV;
> +		goto out_err;
> +	}
> +
> +	/* Take control of the TPM's interrupt hardware and shut it off */
> +	intmask = tpm_read_dword(chip, TPM_INT_ENABLE(chip->vendor.locality));
> +	intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
> +		   TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
> +	intmask &= ~TPM_GLOBAL_INT_ENABLE;
> +	tpm_write_dword(chip, TPM_INT_ENABLE(chip->vendor.locality), intmask);
> +
> +	if (request_locality(chip, 0) != 0) {
> +		rc = -ENODEV;
> +		goto out_err;
> +	}
> +
> +	rc = tpm2_probe(chip);
> +	if (rc)
> +		goto out_err;
> +
> +	vendor = tpm_read_dword(chip, TPM_DID_VID(0));
> +	chip->vendor.manufacturer_id = vendor;
> +
> +	dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n",
> +		 (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2",
> +		 vendor >> 16, tpm_read_byte(chip, TPM_RID(0)));
> +
> +	if (!chip->vendor.itpm) {
> +		probe = probe_itpm(chip);
> +		if (probe < 0) {
> +			rc = -ENODEV;
> +			goto out_err;
> +		}
> +		chip->vendor.itpm = !!probe;
> +	}
> +
> +	if (chip->vendor.itpm)
> +		dev_info(dev, "Intel iTPM workaround enabled\n");
> +
> +	/* Figure out the capabilities */
> +	intfcaps = tpm_read_dword(chip, TPM_INTF_CAPS(chip->vendor.locality));
> +	dev_dbg(dev, "TPM interface capabilities (0x%x):\n", intfcaps);
> +	if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
> +		dev_dbg(dev, "\tBurst Count Static\n");
> +	if (intfcaps & TPM_INTF_CMD_READY_INT)
> +		dev_dbg(dev, "\tCommand Ready Int Support\n");
> +	if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
> +		dev_dbg(dev, "\tInterrupt Edge Falling\n");
> +	if (intfcaps & TPM_INTF_INT_EDGE_RISING)
> +		dev_dbg(dev, "\tInterrupt Edge Rising\n");
> +	if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
> +		dev_dbg(dev, "\tInterrupt Level Low\n");
> +	if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
> +		dev_dbg(dev, "\tInterrupt Level High\n");
> +	if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
> +		dev_dbg(dev, "\tLocality Change Int Support\n");
> +	if (intfcaps & TPM_INTF_STS_VALID_INT)
> +		dev_dbg(dev, "\tSts Valid Int Support\n");
> +	if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
> +		dev_dbg(dev, "\tData Avail Int Support\n");
> +
> +	/* Very early on issue a command to the TPM in polling mode to make
> +	 * sure it works. May as well use that command to set the proper
> +	 *  timeouts for the driver.
> +	 */
> +	if (tpm_get_timeouts(chip)) {
> +		dev_err(dev, "Could not get TPM timeouts and durations\n");
> +		rc = -ENODEV;
> +		goto out_err;
> +	}
> +
> +	/* INTERRUPT Setup */
> +	init_waitqueue_head(&chip->vendor.read_queue);
> +	init_waitqueue_head(&chip->vendor.int_queue);
> +	if (irq > 0) {
> +		tpm_tis_probe_irq_single(chip, intmask, irq_flags, irq);
> +		if (!chip->vendor.irq)
> +			dev_err(&chip->dev, FW_BUG
> +				"TPM interrupt not working, polling instead\n");
> +	} else if (irq != -1) {
> +		tpm_tis_probe_irq(chip, intmask);
> +	}
> +
> +	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
> +		rc = tpm2_do_selftest(chip);
> +		if (rc == TPM2_RC_INITIALIZE) {
> +			dev_warn(dev, "Firmware has not started TPM\n");
> +			rc  = tpm2_startup(chip, TPM2_SU_CLEAR);
> +			if (!rc)
> +				rc = tpm2_do_selftest(chip);
> +		}
> +
> +		if (rc) {
> +			dev_err(dev, "TPM self test failed\n");
> +			if (rc > 0)
> +				rc = -ENODEV;
> +			goto out_err;
> +		}
> +	} else {
> +		if (tpm_do_selftest(chip)) {
> +			dev_err(dev, "TPM self test failed\n");
> +			rc = -ENODEV;
> +			goto out_err;
> +		}
> +	}
> +
> +	return tpm_chip_register(chip);
> +
> +out_err:
> +	return rc;
> +}
> +EXPORT_SYMBOL(tpm_tis_init_core);
> +
> +#ifdef CONFIG_PM_SLEEP
> +static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
> +{
> +	u32 intmask;
> +
> +	/* reenable interrupts that device may have lost or
> +	 * BIOS/firmware may have disabled
> +	 */
> +	tpm_write_byte(chip, TPM_INT_VECTOR(chip->vendor.locality), chip->vendor.irq);
> +
> +
> +	intmask = tpm_read_dword(chip, TPM_INT_ENABLE(chip->vendor.locality));
> +
> +	intmask |= TPM_INTF_CMD_READY_INT
> +	    | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
> +	    | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE;
> +
> +	tpm_write_dword(chip, TPM_INT_ENABLE(chip->vendor.locality), intmask);
> +}
> +
> +int tpm_tis_resume(struct device *dev)
> +{
> +	struct tpm_chip *chip = dev_get_drvdata(dev);
> +	int ret;
> +
> +	if (chip->vendor.irq)
> +		tpm_tis_reenable_interrupts(chip);
> +
> +	ret = tpm_pm_resume(dev);
> +	if (ret)
> +		return ret;
> +
> +	/* TPM 1.2 requires self-test on resume. This function actually returns
> +	 * an error code but for unknown reason it isn't handled.
> +	 */
> +	if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
> +		tpm_do_selftest(chip);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(tpm_tis_resume);
> +#endif
> diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
> new file mode 100644
> index 0000000..2e2d188
> --- /dev/null
> +++ b/drivers/char/tpm/tpm_tis_core.h
> @@ -0,0 +1,166 @@
> +/*
> + * Copyright (C) 2005, 2006 IBM Corporation
> + * Copyright (C) 2014, 2015 Intel Corporation
> + *
> + * Authors:
> + * Leendert van Doorn <leendert-aZOuKsOsJu3MbYB6QlFGEg@public.gmane.org>
> + * Kylene Hall <kjhall-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
> + *
> + * Maintained by: <tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
> + *
> + * Device driver for TCG/TCPA TPM (trusted platform module).
> + * Specifications at www.trustedcomputinggroup.org
> + *
> + * This device driver implements the TPM interface as defined in
> + * the TCG TPM Interface Spec version 1.2, revision 1.0.
> + *
> + * 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 the Free Software Foundation, version 2 of the
> + * License.
> + */
> +
> +#ifndef __TPM_TIS_CORE_H
> +#define __TPM_TIS_CORE_H
> +
> +#include "tpm.h"
> +
> +enum tis_access {
> +	TPM_ACCESS_VALID = 0x80,
> +	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
> +	TPM_ACCESS_REQUEST_PENDING = 0x04,
> +	TPM_ACCESS_REQUEST_USE = 0x02,
> +};
> +
> +enum tis_status {
> +	TPM_STS_VALID = 0x80,
> +	TPM_STS_COMMAND_READY = 0x40,
> +	TPM_STS_GO = 0x20,
> +	TPM_STS_DATA_AVAIL = 0x10,
> +	TPM_STS_DATA_EXPECT = 0x08,
> +	TPM_STS_RESPONSE_RETRY = 0x02,
> +};
> +
> +enum tis_int_flags {
> +	TPM_GLOBAL_INT_ENABLE = 0x80000000,
> +	TPM_INTF_BURST_COUNT_STATIC = 0x100,
> +	TPM_INTF_CMD_READY_INT = 0x080,
> +	TPM_INTF_INT_EDGE_FALLING = 0x040,
> +	TPM_INTF_INT_EDGE_RISING = 0x020,
> +	TPM_INTF_INT_LEVEL_LOW = 0x010,
> +	TPM_INTF_INT_LEVEL_HIGH = 0x008,
> +	TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
> +	TPM_INTF_STS_VALID_INT = 0x002,
> +	TPM_INTF_DATA_AVAIL_INT = 0x001,
> +};
> +
> +enum tis_defaults {
> +	TIS_MEM_BASE = 0xFED40000,
> +	TIS_MEM_LEN = 0x5000,
> +	TIS_SHORT_TIMEOUT = 750,	/* ms */
> +	TIS_LONG_TIMEOUT = 2000,	/* 2 sec */
> +};
> +
> +/* Some timeout values are needed before it is known whether the chip is
> + * TPM 1.0 or TPM 2.0.
> + */
> +#define TIS_TIMEOUT_A_MAX	max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_A)
> +#define TIS_TIMEOUT_B_MAX	max(TIS_LONG_TIMEOUT, TPM2_TIMEOUT_B)
> +#define TIS_TIMEOUT_C_MAX	max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_C)
> +#define TIS_TIMEOUT_D_MAX	max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_D)
> +
> +#define	TPM_ACCESS(l)			(0x0000 | ((l) << 12))
> +#define	TPM_INT_ENABLE(l)		(0x0008 | ((l) << 12))
> +#define	TPM_INT_VECTOR(l)		(0x000C | ((l) << 12))
> +#define	TPM_INT_STATUS(l)		(0x0010 | ((l) << 12))
> +#define	TPM_INTF_CAPS(l)		(0x0014 | ((l) << 12))
> +#define	TPM_STS(l)			(0x0018 | ((l) << 12))
> +#define	TPM_STS3(l)			(0x001b | ((l) << 12))
> +#define	TPM_DATA_FIFO(l)		(0x0024 | ((l) << 12))
> +
> +#define	TPM_DID_VID(l)			(0x0F00 | ((l) << 12))
> +#define	TPM_RID(l)			(0x0F04 | ((l) << 12))
> +
> +struct tis_vendor_timeout_override {
> +	u32 did_vid;
> +	unsigned long timeout_us[4];
> +};
> +
> +static const struct tis_vendor_timeout_override vendor_timeout_overrides[] = {
> +	/* Atmel 3204 */
> +	{ 0x32041114, { (TIS_SHORT_TIMEOUT * 1000), (TIS_LONG_TIMEOUT * 1000),
> +			(TIS_SHORT_TIMEOUT * 1000), (TIS_SHORT_TIMEOUT * 1000) } },
> +};
> +
> +u8 tpm_tis_status(struct tpm_chip *chip);
> +void tpm_tis_ready(struct tpm_chip *chip);
> +int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count);
> +int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len);
> +bool tpm_tis_update_timeouts(struct tpm_chip *chip,
> +				    unsigned long *timeout_cap);
> +bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status);
> +int tpm_tis_resume(struct device *dev);
> +void tpm_tis_remove(struct tpm_chip *chip);
> +
> +/* Helpers - read */
> +static inline int tpm_read_bytes(struct tpm_chip *chip, u32 addr,
> +				 size_t len, u8 *res)
> +{
> +	return chip->ops->read_bytes(chip, addr, len, 1, res);
> +}
> +static inline u8 tpm_read_byte(struct tpm_chip *chip, u32 addr)
> +{
> +	u8 res;
> +
> +	chip->ops->read_bytes(chip, addr, 1, sizeof(u8), &res);
> +
> +	return res;
> +}
> +
> +static inline u16 tpm_read_word(struct tpm_chip *chip, u32 addr)
> +{
> +	u16 res;
> +
> +	chip->ops->read_bytes(chip, addr, 1, sizeof(u16), (u8 *)&res);
> +	return res;
> +}
> +
> +static inline u32 tpm_read_dword(struct tpm_chip *chip, u32 addr)
> +{
> +	u32 res;
> +
> +	chip->ops->read_bytes(chip, addr, 1, sizeof(u32), (u8 *)&res);
> +	return res;
> +}
> +
> +/* Helpers - write */
> +static inline int tpm_write_bytes(struct tpm_chip *chip, u32 addr,
> +				  size_t len, u8 *value)
> +{
> +	return chip->ops->write_bytes(chip, addr, 1, len, value);
> +}
> +
> +static inline int tpm_write_byte(struct tpm_chip *chip, u32 addr, u8 value)
> +{
> +	u8 tmp = value;
> +
> +	return chip->ops->write_bytes(chip, addr, 1, sizeof(u8), &tmp);
> +}
> +
> +static inline int tpm_write_word(struct tpm_chip *chip, u32 addr, u16 value)
> +{
> +	u32 tmp = value;
> +
> +	return chip->ops->write_bytes(chip, addr, 1, sizeof(u16), (u8 *)&tmp);
> +}
> +
> +static inline int tpm_write_dword(struct tpm_chip *chip, u32 addr, u32 value)
> +{
> +	u32 tmp = value;
> +
> +	return chip->ops->write_bytes(chip, addr, 1, sizeof(u32), (u8 *)&tmp);
> +}
> +
> +int tpm_tis_init_core(struct device *dev, struct tpm_chip *chip,
> +		      int irq, int irq_flags);
> +#endif
> diff --git a/include/linux/tpm.h b/include/linux/tpm.h
> index 706e63e..f78e4fc 100644
> --- a/include/linux/tpm.h
> +++ b/include/linux/tpm.h
> @@ -44,6 +44,10 @@ struct tpm_class_ops {
>  	bool (*update_timeouts)(struct tpm_chip *chip,
>  				unsigned long *timeout_cap);
>  
> +	int (*read_bytes)(struct tpm_chip *chip, u32 addr, size_t len,
> +			  u8 size, u8 *dst);
> +	int (*write_bytes)(struct tpm_chip *chip, u32 addr, size_t len,
> +			   u8 size, u8 *src);
>  };
>  
>  #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE)
> -- 
> 2.5.0
> 

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 05/12] tpm: Add tpm_set_vendordata and tpm_get_vendordata
       [not found]         ` <20160322062001.GB4058-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
@ 2016-03-22 15:58           ` Jason Gunthorpe
       [not found]             ` <20160322155824.GA25600-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
  2016-03-23 13:11           ` Christophe Ricard
  1 sibling, 1 reply; 39+ messages in thread
From: Jason Gunthorpe @ 2016-03-22 15:58 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Christophe Ricard, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	jean-luc.blanc-qxv4g6HH51o,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

On Tue, Mar 22, 2016 at 08:20:01AM +0200, Jarkko Sakkinen wrote:
> On Sun, Mar 20, 2016 at 08:34:36PM +0100, Christophe Ricard wrote:
> > Remove TPM_VPRIV macro and replace with tpm_set_vendordata and
> > tpm_get_vendordata.
> 
> NAK. These unnecessary wrapper functions make code just harder to read.
> I'd rather accept a patch that would drop TPM_VPRIV and not introduce
> new clutter.

We should be getting pretty close to being able to use drvdata on the
chip->dev for this sort of stuff...

Jason

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 05/12] tpm: Add tpm_set_vendordata and tpm_get_vendordata
       [not found]             ` <20160322155824.GA25600-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
@ 2016-03-22 16:00               ` Christophe Ricard
  0 siblings, 0 replies; 39+ messages in thread
From: Christophe Ricard @ 2016-03-22 16:00 UTC (permalink / raw)
  To: Jason Gunthorpe, Jarkko Sakkinen
  Cc: jean-luc.blanc-qxv4g6HH51o, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	christophe-h.ricard-qxv4g6HH51o, benoit.houyere-qxv4g6HH51o

Hi Jason, Jarkko,

I think i found some way to get to it.

I will share something as soon as it is ready.

Best Regards
Christophe

On 22/03/2016 16:58, Jason Gunthorpe wrote:
> On Tue, Mar 22, 2016 at 08:20:01AM +0200, Jarkko Sakkinen wrote:
>> On Sun, Mar 20, 2016 at 08:34:36PM +0100, Christophe Ricard wrote:
>>> Remove TPM_VPRIV macro and replace with tpm_set_vendordata and
>>> tpm_get_vendordata.
>> NAK. These unnecessary wrapper functions make code just harder to read.
>> I'd rather accept a patch that would drop TPM_VPRIV and not introduce
>> new clutter.
> We should be getting pretty close to being able to use drvdata on the
> chip->dev for this sort of stuff...
>
> Jason


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 05/12] tpm: Add tpm_set_vendordata and tpm_get_vendordata
       [not found]         ` <20160322062001.GB4058-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
  2016-03-22 15:58           ` Jason Gunthorpe
@ 2016-03-23 13:11           ` Christophe Ricard
       [not found]             ` <CALD+uuxj2NHd0-LpDZpnfkfMHwY6ke0FPPqmR0FKzrC4BJmFNQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  1 sibling, 1 reply; 39+ messages in thread
From: Christophe Ricard @ 2016-03-23 13:11 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Jean-Luc BLANC, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Christophe RICARD,
	Benoit HOUYERE


[-- Attachment #1.1: Type: text/plain, Size: 12435 bytes --]

Hi Jarkko,

Just coming back to you on this one. My intention was mainly align the
"code style" from my eyes with other similar functions from other
subsystems.
For example and coming to my mind:
i2c: i2c_get_clientdata/i2c_set_clientdata
spi: spi_get_drvdata/spi_set_drvdata
nfc: nfc_get_drvdata/nfc_set_drvdata

In the mean time when trying to cleanup the code i found helpers with the
exact same purpose in tpm_atmel.h (atmel_get_priv) or tpm_nsc.c
(tpm_nsc_get_priv).

When working on the tpm_vendor_specific cleanup, i came also through the
conclusion that moving priv from tpm_vendor_specific to tpm_chip structure
would the most
simple and appropriate solution in short term.

...priv field may be renamed data...

Do you see anything against a serie removing atmel_get_priv and
tpm_nsc_get_priv and with a common helper replacing TPM_VPRIV ?

Best Regards
Christophe


2016-03-22 7:20 GMT+01:00 Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>:

> On Sun, Mar 20, 2016 at 08:34:36PM +0100, Christophe Ricard wrote:
> > Remove TPM_VPRIV macro and replace with tpm_set_vendordata and
> > tpm_get_vendordata.
>
> NAK. These unnecessary wrapper functions make code just harder to read.
> I'd rather accept a patch that would drop TPM_VPRIV and not introduce
> new clutter.
>
> /Jarkko
>
> > Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
> > ---
> >  drivers/char/tpm/st33zp24/st33zp24.c | 26 +++++++++++++-------------
> >  drivers/char/tpm/tpm.h               | 12 ++++++++++--
> >  drivers/char/tpm/tpm_ibmvtpm.c       |  8 ++++----
> >  drivers/char/tpm/tpm_tis.c           |  2 +-
> >  drivers/char/tpm/xen-tpmfront.c      | 14 +++++++-------
> >  5 files changed, 35 insertions(+), 27 deletions(-)
> >
> > diff --git a/drivers/char/tpm/st33zp24/st33zp24.c
> b/drivers/char/tpm/st33zp24/st33zp24.c
> > index 9e91ca7..dc2d0f3 100644
> > --- a/drivers/char/tpm/st33zp24/st33zp24.c
> > +++ b/drivers/char/tpm/st33zp24/st33zp24.c
> > @@ -105,7 +105,7 @@ static void st33zp24_cancel(struct tpm_chip *chip)
> >       struct st33zp24_dev *tpm_dev;
> >       u8 data;
> >
> > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >
> >       data = TPM_STS_COMMAND_READY;
> >       tpm_dev->ops->send(tpm_dev->phy_id, TPM_STS, &data, 1);
> > @@ -121,7 +121,7 @@ static u8 st33zp24_status(struct tpm_chip *chip)
> >       struct st33zp24_dev *tpm_dev;
> >       u8 data;
> >
> > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >
> >       tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS, &data, 1);
> >       return data;
> > @@ -138,7 +138,7 @@ static int check_locality(struct tpm_chip *chip)
> >       u8 data;
> >       u8 status;
> >
> > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >
> >       status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
> >       if (status && (data &
> > @@ -164,7 +164,7 @@ static int request_locality(struct tpm_chip *chip)
> >       if (check_locality(chip) == chip->vendor.locality)
> >               return chip->vendor.locality;
> >
> > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >
> >       data = TPM_ACCESS_REQUEST_USE;
> >       ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
> > @@ -193,7 +193,7 @@ static void release_locality(struct tpm_chip *chip)
> >       struct st33zp24_dev *tpm_dev;
> >       u8 data;
> >
> > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >       data = TPM_ACCESS_ACTIVE_LOCALITY;
> >
> >       tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
> > @@ -211,7 +211,7 @@ static int get_burstcount(struct tpm_chip *chip)
> >       u8 temp;
> >       struct st33zp24_dev *tpm_dev;
> >
> > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >
> >       stop = jiffies + chip->vendor.timeout_d;
> >       do {
> > @@ -279,7 +279,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8
> mask, unsigned long timeout,
> >       u8 status;
> >       struct st33zp24_dev *tpm_dev;
> >
> > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >
> >       /* check current status */
> >       status = st33zp24_status(chip);
> > @@ -340,7 +340,7 @@ static int recv_data(struct tpm_chip *chip, u8 *buf,
> size_t count)
> >       int size = 0, burstcnt, len, ret;
> >       struct st33zp24_dev *tpm_dev;
> >
> > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >
> >       while (size < count &&
> >              wait_for_stat(chip,
> > @@ -372,7 +372,7 @@ 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);
> > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >
> >       tpm_dev->intrs++;
> >       wake_up_interruptible(&chip->vendor.read_queue);
> > @@ -404,7 +404,7 @@ static int st33zp24_send(struct tpm_chip *chip,
> unsigned char *buf,
> >       if (len < TPM_HEADER_SIZE)
> >               return -EBUSY;
> >
> > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >
> >       ret = request_locality(chip);
> >       if (ret < 0)
> > @@ -565,7 +565,7 @@ int st33zp24_probe(void *phy_id, const struct
> st33zp24_phy_ops *ops,
> >       if (!tpm_dev)
> >               return -ENOMEM;
> >
> > -     TPM_VPRIV(chip) = tpm_dev;
> > +     tpm_set_vendordata(chip, tpm_dev);
> >       tpm_dev->phy_id = phy_id;
> >       tpm_dev->ops = ops;
> >
> > @@ -653,7 +653,7 @@ int st33zp24_pm_suspend(struct device *dev)
> >       struct st33zp24_dev *tpm_dev;
> >       int ret = 0;
> >
> > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >
> >       if (gpio_is_valid(tpm_dev->io_lpcpd))
> >               gpio_set_value(tpm_dev->io_lpcpd, 0);
> > @@ -675,7 +675,7 @@ int st33zp24_pm_resume(struct device *dev)
> >       struct st33zp24_dev *tpm_dev;
> >       int ret = 0;
> >
> > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >
> >       if (gpio_is_valid(tpm_dev->io_lpcpd)) {
> >               gpio_set_value(tpm_dev->io_lpcpd, 1);
> > diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> > index 28a0c17..6a973b9 100644
> > --- a/drivers/char/tpm/tpm.h
> > +++ b/drivers/char/tpm/tpm.h
> > @@ -157,8 +157,6 @@ struct tpm_vendor_specific {
> >       u16 manufacturer_id;
> >  };
> >
> > -#define TPM_VPRIV(c)     ((c)->vendor.priv)
> > -
> >  #define TPM_VID_INTEL    0x8086
> >  #define TPM_VID_WINBOND  0x1050
> >  #define TPM_VID_STM      0x104A
> > @@ -203,6 +201,16 @@ struct tpm_chip {
> >
> >  #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
> >
> > +static inline void tpm_set_vendordata(struct tpm_chip *chip, void *data)
> > +{
> > +     chip->vendor.priv = data;
> > +}
> > +
> > +static inline void *tpm_get_vendordata(struct tpm_chip *chip)
> > +{
> > +     return chip->vendor.priv;
> > +}
> > +
> >  static inline int tpm_read_index(int base, int index)
> >  {
> >       outb(index, base);
> > diff --git a/drivers/char/tpm/tpm_ibmvtpm.c
> b/drivers/char/tpm/tpm_ibmvtpm.c
> > index b0a9a9e..c8b1643 100644
> > --- a/drivers/char/tpm/tpm_ibmvtpm.c
> > +++ b/drivers/char/tpm/tpm_ibmvtpm.c
> > @@ -64,7 +64,7 @@ static struct ibmvtpm_dev *ibmvtpm_get_data(const
> struct device *dev)
> >  {
> >       struct tpm_chip *chip = dev_get_drvdata(dev);
> >       if (chip)
> > -             return (struct ibmvtpm_dev *)TPM_VPRIV(chip);
> > +             return (struct ibmvtpm_dev *)tpm_get_vendordata(chip);
> >       return NULL;
> >  }
> >
> > @@ -83,7 +83,7 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8
> *buf, size_t count)
> >       u16 len;
> >       int sig;
> >
> > -     ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
> > +     ibmvtpm = (struct ibmvtpm_dev *)tpm_get_vendordata(chip);
> >
> >       if (!ibmvtpm->rtce_buf) {
> >               dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
> > @@ -127,7 +127,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip,
> u8 *buf, size_t count)
> >       __be64 *word = (__be64 *)&crq;
> >       int rc, sig;
> >
> > -     ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
> > +     ibmvtpm = (struct ibmvtpm_dev *)tpm_get_vendordata(chip);
> >
> >       if (!ibmvtpm->rtce_buf) {
> >               dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
> > @@ -643,7 +643,7 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
> >
> >       crq_q->index = 0;
> >
> > -     TPM_VPRIV(chip) = (void *)ibmvtpm;
> > +     tpm_set_vendordata(chip, (void *)ibmvtpm);
> >
> >       spin_lock_init(&ibmvtpm->rtce_lock);
> >
> > diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
> > index eed3bf5..607fa3f 100644
> > --- a/drivers/char/tpm/tpm_tis.c
> > +++ b/drivers/char/tpm/tpm_tis.c
> > @@ -678,7 +678,7 @@ static int tpm_tis_init(struct device *dev, struct
> tpm_info *tpm_info,
> >       if (IS_ERR(chip))
> >               return PTR_ERR(chip);
> >
> > -     chip->vendor.priv = priv;
> > +     tpm_set_vendordata(chip, priv);
> >  #ifdef CONFIG_ACPI
> >       chip->acpi_dev_handle = acpi_dev_handle;
> >  #endif
> > diff --git a/drivers/char/tpm/xen-tpmfront.c
> b/drivers/char/tpm/xen-tpmfront.c
> > index 3111f27..c472fd8 100644
> > --- a/drivers/char/tpm/xen-tpmfront.c
> > +++ b/drivers/char/tpm/xen-tpmfront.c
> > @@ -39,7 +39,7 @@ enum status_bits {
> >
> >  static u8 vtpm_status(struct tpm_chip *chip)
> >  {
> > -     struct tpm_private *priv = TPM_VPRIV(chip);
> > +     struct tpm_private *priv = tpm_get_vendordata(chip);
> >       switch (priv->shr->state) {
> >       case VTPM_STATE_IDLE:
> >               return VTPM_STATUS_IDLE | VTPM_STATUS_CANCELED;
> > @@ -60,7 +60,7 @@ static bool vtpm_req_canceled(struct tpm_chip *chip,
> u8 status)
> >
> >  static void vtpm_cancel(struct tpm_chip *chip)
> >  {
> > -     struct tpm_private *priv = TPM_VPRIV(chip);
> > +     struct tpm_private *priv = tpm_get_vendordata(chip);
> >       priv->shr->state = VTPM_STATE_CANCEL;
> >       wmb();
> >       notify_remote_via_evtchn(priv->evtchn);
> > @@ -73,7 +73,7 @@ static unsigned int shr_data_offset(struct
> vtpm_shared_page *shr)
> >
> >  static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
> >  {
> > -     struct tpm_private *priv = TPM_VPRIV(chip);
> > +     struct tpm_private *priv = tpm_get_vendordata(chip);
> >       struct vtpm_shared_page *shr = priv->shr;
> >       unsigned int offset = shr_data_offset(shr);
> >
> > @@ -115,7 +115,7 @@ static int vtpm_send(struct tpm_chip *chip, u8 *buf,
> size_t count)
> >
> >  static int vtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
> >  {
> > -     struct tpm_private *priv = TPM_VPRIV(chip);
> > +     struct tpm_private *priv = tpm_get_vendordata(chip);
> >       struct vtpm_shared_page *shr = priv->shr;
> >       unsigned int offset = shr_data_offset(shr);
> >       size_t length = shr->length;
> > @@ -182,7 +182,7 @@ static int setup_chip(struct device *dev, struct
> tpm_private *priv)
> >       init_waitqueue_head(&chip->vendor.read_queue);
> >
> >       priv->chip = chip;
> > -     TPM_VPRIV(chip) = priv;
> > +     tpm_set_vendordata(chip, priv);
> >
> >       return 0;
> >  }
> > @@ -318,10 +318,10 @@ static int tpmfront_probe(struct xenbus_device
> *dev,
> >  static int tpmfront_remove(struct xenbus_device *dev)
> >  {
> >       struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
> > -     struct tpm_private *priv = TPM_VPRIV(chip);
> > +     struct tpm_private *priv = tpm_get_vendordata(chip);
> >       tpm_chip_unregister(chip);
> >       ring_free(priv);
> > -     TPM_VPRIV(chip) = NULL;
> > +     tpm_set_vendordata(chip, NULL);
> >       return 0;
> >  }
> >
> > --
> > 2.5.0
> >
>

[-- Attachment #1.2: Type: text/html, Size: 15734 bytes --]

[-- Attachment #2: Type: text/plain, Size: 291 bytes --]

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

[-- Attachment #3: Type: text/plain, Size: 192 bytes --]

_______________________________________________
tpmdd-devel mailing list
tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/tpmdd-devel

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 05/12] tpm: Add tpm_set_vendordata and tpm_get_vendordata
       [not found]             ` <CALD+uuxj2NHd0-LpDZpnfkfMHwY6ke0FPPqmR0FKzrC4BJmFNQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2016-03-23 16:48               ` Jason Gunthorpe
  2016-03-24 13:27               ` Jarkko Sakkinen
  1 sibling, 0 replies; 39+ messages in thread
From: Jason Gunthorpe @ 2016-03-23 16:48 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: Jean-Luc BLANC, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Christophe RICARD,
	Benoit HOUYERE

On Wed, Mar 23, 2016 at 02:11:26PM +0100, Christophe Ricard wrote:
>    When working on the tpm_vendor_specific cleanup, i came also through
>    the conclusion that moving priv from tpm_vendor_specific to tpm_chip
>    structure would the most
>    simple and appropriate solution in short term.

Someday, but we really should just use chip->dev drvdata for 'priv'

>    ...priv field may be renamed data...
>    Do you see anything against a serie removing atmel_get_priv and
>    tpm_nsc_get_priv and with a common helper replacing TPM_VPRIV ?

These functions include a cast, they can't be generic.

Jason

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 05/12] tpm: Add tpm_set_vendordata and tpm_get_vendordata
       [not found]             ` <CALD+uuxj2NHd0-LpDZpnfkfMHwY6ke0FPPqmR0FKzrC4BJmFNQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2016-03-23 16:48               ` Jason Gunthorpe
@ 2016-03-24 13:27               ` Jarkko Sakkinen
       [not found]                 ` <20160324132732.GF8452-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
  1 sibling, 1 reply; 39+ messages in thread
From: Jarkko Sakkinen @ 2016-03-24 13:27 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: Jean-Luc BLANC, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Christophe RICARD,
	Benoit HOUYERE

On Wed, Mar 23, 2016 at 02:11:26PM +0100, Christophe Ricard wrote:
>    Hi Jarkko,
> 
>    Just coming back to you on this one. My intention was mainly align the
>    "code style" from my eyes with other similar functions from other
>    subsystems.
>    For example and coming to my mind:
>    i2c: i2c_get_clientdata/i2c_set_clientdata
>    spi: spi_get_drvdata/spi_set_drvdata
>    nfc: nfc_get_drvdata/nfc_set_drvdata
> 
>    In the mean time when trying to cleanup the code i found helpers with the
>    exact same purpose in tpm_atmel.h (atmel_get_priv) or tpm_nsc.c
>    (tpm_nsc_get_priv).
> 
>    When working on the tpm_vendor_specific cleanup, i came also through the
>    conclusion that moving priv from tpm_vendor_specific to tpm_chip structure
>    would the most
>    simple and appropriate solution in short term.
> 
>    ...priv field may be renamed data...
>    Do you see anything against a serie removing atmel_get_priv and
>    tpm_nsc_get_priv and with a common helper replacing TPM_VPRIV ?

Yes I do. The current problem is that HW specific stuff lives in the
framework and not in the drivers for that HW. I would like to see HW
drivers to use priv for their internal and get rid off
tpm_vendor_specific completely.

/Jarkko

>    Best Regards
>    Christophe
>    2016-03-22 7:20 GMT+01:00 Jarkko Sakkinen
>    <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>:
> 
>      On Sun, Mar 20, 2016 at 08:34:36PM +0100, Christophe Ricard wrote:
>      > Remove TPM_VPRIV macro and replace with tpm_set_vendordata and
>      > tpm_get_vendordata.
> 
>      NAK. These unnecessary wrapper functions make code just harder to read.
>      I'd rather accept a patch that would drop TPM_VPRIV and not introduce
>      new clutter.
>      /Jarkko
>      > Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
>      > ---
>      >  drivers/char/tpm/st33zp24/st33zp24.c | 26 +++++++++++++-------------
>      >  drivers/char/tpm/tpm.h               | 12 ++++++++++--
>      >  drivers/char/tpm/tpm_ibmvtpm.c       |  8 ++++----
>      >  drivers/char/tpm/tpm_tis.c           |  2 +-
>      >  drivers/char/tpm/xen-tpmfront.c      | 14 +++++++-------
>      >  5 files changed, 35 insertions(+), 27 deletions(-)
>      >
>      > diff --git a/drivers/char/tpm/st33zp24/st33zp24.c
>      b/drivers/char/tpm/st33zp24/st33zp24.c
>      > index 9e91ca7..dc2d0f3 100644
>      > --- a/drivers/char/tpm/st33zp24/st33zp24.c
>      > +++ b/drivers/char/tpm/st33zp24/st33zp24.c
>      > @@ -105,7 +105,7 @@ static void st33zp24_cancel(struct tpm_chip *chip)
>      >       struct st33zp24_dev *tpm_dev;
>      >       u8 data;
>      >
>      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
>      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>      >
>      >       data = TPM_STS_COMMAND_READY;
>      >       tpm_dev->ops->send(tpm_dev->phy_id, TPM_STS, &data, 1);
>      > @@ -121,7 +121,7 @@ static u8 st33zp24_status(struct tpm_chip *chip)
>      >       struct st33zp24_dev *tpm_dev;
>      >       u8 data;
>      >
>      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
>      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>      >
>      >       tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS, &data, 1);
>      >       return data;
>      > @@ -138,7 +138,7 @@ static int check_locality(struct tpm_chip *chip)
>      >       u8 data;
>      >       u8 status;
>      >
>      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
>      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>      >
>      >       status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_ACCESS,
>      &data, 1);
>      >       if (status && (data &
>      > @@ -164,7 +164,7 @@ static int request_locality(struct tpm_chip *chip)
>      >       if (check_locality(chip) == chip->vendor.locality)
>      >               return chip->vendor.locality;
>      >
>      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
>      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>      >
>      >       data = TPM_ACCESS_REQUEST_USE;
>      >       ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data,
>      1);
>      > @@ -193,7 +193,7 @@ static void release_locality(struct tpm_chip
>      *chip)
>      >       struct st33zp24_dev *tpm_dev;
>      >       u8 data;
>      >
>      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
>      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>      >       data = TPM_ACCESS_ACTIVE_LOCALITY;
>      >
>      >       tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
>      > @@ -211,7 +211,7 @@ static int get_burstcount(struct tpm_chip *chip)
>      >       u8 temp;
>      >       struct st33zp24_dev *tpm_dev;
>      >
>      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
>      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>      >
>      >       stop = jiffies + chip->vendor.timeout_d;
>      >       do {
>      > @@ -279,7 +279,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8
>      mask, unsigned long timeout,
>      >       u8 status;
>      >       struct st33zp24_dev *tpm_dev;
>      >
>      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
>      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>      >
>      >       /* check current status */
>      >       status = st33zp24_status(chip);
>      > @@ -340,7 +340,7 @@ static int recv_data(struct tpm_chip *chip, u8
>      *buf, size_t count)
>      >       int size = 0, burstcnt, len, ret;
>      >       struct st33zp24_dev *tpm_dev;
>      >
>      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
>      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>      >
>      >       while (size < count &&
>      >              wait_for_stat(chip,
>      > @@ -372,7 +372,7 @@ 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);
>      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>      >
>      >       tpm_dev->intrs++;
>      >       wake_up_interruptible(&chip->vendor.read_queue);
>      > @@ -404,7 +404,7 @@ static int st33zp24_send(struct tpm_chip *chip,
>      unsigned char *buf,
>      >       if (len < TPM_HEADER_SIZE)
>      >               return -EBUSY;
>      >
>      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
>      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>      >
>      >       ret = request_locality(chip);
>      >       if (ret < 0)
>      > @@ -565,7 +565,7 @@ int st33zp24_probe(void *phy_id, const struct
>      st33zp24_phy_ops *ops,
>      >       if (!tpm_dev)
>      >               return -ENOMEM;
>      >
>      > -     TPM_VPRIV(chip) = tpm_dev;
>      > +     tpm_set_vendordata(chip, tpm_dev);
>      >       tpm_dev->phy_id = phy_id;
>      >       tpm_dev->ops = ops;
>      >
>      > @@ -653,7 +653,7 @@ int st33zp24_pm_suspend(struct device *dev)
>      >       struct st33zp24_dev *tpm_dev;
>      >       int ret = 0;
>      >
>      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
>      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>      >
>      >       if (gpio_is_valid(tpm_dev->io_lpcpd))
>      >               gpio_set_value(tpm_dev->io_lpcpd, 0);
>      > @@ -675,7 +675,7 @@ int st33zp24_pm_resume(struct device *dev)
>      >       struct st33zp24_dev *tpm_dev;
>      >       int ret = 0;
>      >
>      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
>      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
>      >
>      >       if (gpio_is_valid(tpm_dev->io_lpcpd)) {
>      >               gpio_set_value(tpm_dev->io_lpcpd, 1);
>      > diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
>      > index 28a0c17..6a973b9 100644
>      > --- a/drivers/char/tpm/tpm.h
>      > +++ b/drivers/char/tpm/tpm.h
>      > @@ -157,8 +157,6 @@ struct tpm_vendor_specific {
>      >       u16 manufacturer_id;
>      >  };
>      >
>      > -#define TPM_VPRIV(c)     ((c)->vendor.priv)
>      > -
>      >  #define TPM_VID_INTEL    0x8086
>      >  #define TPM_VID_WINBOND  0x1050
>      >  #define TPM_VID_STM      0x104A
>      > @@ -203,6 +201,16 @@ struct tpm_chip {
>      >
>      >  #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
>      >
>      > +static inline void tpm_set_vendordata(struct tpm_chip *chip, void
>      *data)
>      > +{
>      > +     chip->vendor.priv = data;
>      > +}
>      > +
>      > +static inline void *tpm_get_vendordata(struct tpm_chip *chip)
>      > +{
>      > +     return chip->vendor.priv;
>      > +}
>      > +
>      >  static inline int tpm_read_index(int base, int index)
>      >  {
>      >       outb(index, base);
>      > diff --git a/drivers/char/tpm/tpm_ibmvtpm.c
>      b/drivers/char/tpm/tpm_ibmvtpm.c
>      > index b0a9a9e..c8b1643 100644
>      > --- a/drivers/char/tpm/tpm_ibmvtpm.c
>      > +++ b/drivers/char/tpm/tpm_ibmvtpm.c
>      > @@ -64,7 +64,7 @@ static struct ibmvtpm_dev *ibmvtpm_get_data(const
>      struct device *dev)
>      >  {
>      >       struct tpm_chip *chip = dev_get_drvdata(dev);
>      >       if (chip)
>      > -             return (struct ibmvtpm_dev *)TPM_VPRIV(chip);
>      > +             return (struct ibmvtpm_dev
>      *)tpm_get_vendordata(chip);
>      >       return NULL;
>      >  }
>      >
>      > @@ -83,7 +83,7 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip,
>      u8 *buf, size_t count)
>      >       u16 len;
>      >       int sig;
>      >
>      > -     ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
>      > +     ibmvtpm = (struct ibmvtpm_dev *)tpm_get_vendordata(chip);
>      >
>      >       if (!ibmvtpm->rtce_buf) {
>      >               dev_err(ibmvtpm->dev, "ibmvtpm device is not
>      ready\n");
>      > @@ -127,7 +127,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip,
>      u8 *buf, size_t count)
>      >       __be64 *word = (__be64 *)&crq;
>      >       int rc, sig;
>      >
>      > -     ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
>      > +     ibmvtpm = (struct ibmvtpm_dev *)tpm_get_vendordata(chip);
>      >
>      >       if (!ibmvtpm->rtce_buf) {
>      >               dev_err(ibmvtpm->dev, "ibmvtpm device is not
>      ready\n");
>      > @@ -643,7 +643,7 @@ static int tpm_ibmvtpm_probe(struct vio_dev
>      *vio_dev,
>      >
>      >       crq_q->index = 0;
>      >
>      > -     TPM_VPRIV(chip) = (void *)ibmvtpm;
>      > +     tpm_set_vendordata(chip, (void *)ibmvtpm);
>      >
>      >       spin_lock_init(&ibmvtpm->rtce_lock);
>      >
>      > diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
>      > index eed3bf5..607fa3f 100644
>      > --- a/drivers/char/tpm/tpm_tis.c
>      > +++ b/drivers/char/tpm/tpm_tis.c
>      > @@ -678,7 +678,7 @@ static int tpm_tis_init(struct device *dev, struct
>      tpm_info *tpm_info,
>      >       if (IS_ERR(chip))
>      >               return PTR_ERR(chip);
>      >
>      > -     chip->vendor.priv = priv;
>      > +     tpm_set_vendordata(chip, priv);
>      >  #ifdef CONFIG_ACPI
>      >       chip->acpi_dev_handle = acpi_dev_handle;
>      >  #endif
>      > diff --git a/drivers/char/tpm/xen-tpmfront.c
>      b/drivers/char/tpm/xen-tpmfront.c
>      > index 3111f27..c472fd8 100644
>      > --- a/drivers/char/tpm/xen-tpmfront.c
>      > +++ b/drivers/char/tpm/xen-tpmfront.c
>      > @@ -39,7 +39,7 @@ enum status_bits {
>      >
>      >  static u8 vtpm_status(struct tpm_chip *chip)
>      >  {
>      > -     struct tpm_private *priv = TPM_VPRIV(chip);
>      > +     struct tpm_private *priv = tpm_get_vendordata(chip);
>      >       switch (priv->shr->state) {
>      >       case VTPM_STATE_IDLE:
>      >               return VTPM_STATUS_IDLE | VTPM_STATUS_CANCELED;
>      > @@ -60,7 +60,7 @@ static bool vtpm_req_canceled(struct tpm_chip *chip,
>      u8 status)
>      >
>      >  static void vtpm_cancel(struct tpm_chip *chip)
>      >  {
>      > -     struct tpm_private *priv = TPM_VPRIV(chip);
>      > +     struct tpm_private *priv = tpm_get_vendordata(chip);
>      >       priv->shr->state = VTPM_STATE_CANCEL;
>      >       wmb();
>      >       notify_remote_via_evtchn(priv->evtchn);
>      > @@ -73,7 +73,7 @@ static unsigned int shr_data_offset(struct
>      vtpm_shared_page *shr)
>      >
>      >  static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
>      >  {
>      > -     struct tpm_private *priv = TPM_VPRIV(chip);
>      > +     struct tpm_private *priv = tpm_get_vendordata(chip);
>      >       struct vtpm_shared_page *shr = priv->shr;
>      >       unsigned int offset = shr_data_offset(shr);
>      >
>      > @@ -115,7 +115,7 @@ static int vtpm_send(struct tpm_chip *chip, u8
>      *buf, size_t count)
>      >
>      >  static int vtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
>      >  {
>      > -     struct tpm_private *priv = TPM_VPRIV(chip);
>      > +     struct tpm_private *priv = tpm_get_vendordata(chip);
>      >       struct vtpm_shared_page *shr = priv->shr;
>      >       unsigned int offset = shr_data_offset(shr);
>      >       size_t length = shr->length;
>      > @@ -182,7 +182,7 @@ static int setup_chip(struct device *dev, struct
>      tpm_private *priv)
>      >       init_waitqueue_head(&chip->vendor.read_queue);
>      >
>      >       priv->chip = chip;
>      > -     TPM_VPRIV(chip) = priv;
>      > +     tpm_set_vendordata(chip, priv);
>      >
>      >       return 0;
>      >  }
>      > @@ -318,10 +318,10 @@ static int tpmfront_probe(struct xenbus_device
>      *dev,
>      >  static int tpmfront_remove(struct xenbus_device *dev)
>      >  {
>      >       struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
>      > -     struct tpm_private *priv = TPM_VPRIV(chip);
>      > +     struct tpm_private *priv = tpm_get_vendordata(chip);
>      >       tpm_chip_unregister(chip);
>      >       ring_free(priv);
>      > -     TPM_VPRIV(chip) = NULL;
>      > +     tpm_set_vendordata(chip, NULL);
>      >       return 0;
>      >  }
>      >
>      > --
>      > 2.5.0
>      >

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 05/12] tpm: Add tpm_set_vendordata and tpm_get_vendordata
       [not found]                 ` <20160324132732.GF8452-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
@ 2016-03-24 13:30                   ` Christophe Ricard
       [not found]                     ` <CALD+uuwVG_84dY4rCOjecZXxS4LZoE+Kh=CyhmVwyT2U0bAMrg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 39+ messages in thread
From: Christophe Ricard @ 2016-03-24 13:30 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Jean-Luc BLANC, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Christophe RICARD,
	Benoit HOUYERE


[-- Attachment #1.1: Type: text/plain, Size: 15496 bytes --]

Hi Jarkko,

I am currently working at removing this TPM_VPRIV and priv field as
requested previously.
As pointed by you or Jason, i succeeded to go the dev_get_drvdata way :).

Will send a new serie asap once ready.

Best Regards
Christophe

2016-03-24 14:27 GMT+01:00 Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
:

> On Wed, Mar 23, 2016 at 02:11:26PM +0100, Christophe Ricard wrote:
> >    Hi Jarkko,
> >
> >    Just coming back to you on this one. My intention was mainly align the
> >    "code style" from my eyes with other similar functions from other
> >    subsystems.
> >    For example and coming to my mind:
> >    i2c: i2c_get_clientdata/i2c_set_clientdata
> >    spi: spi_get_drvdata/spi_set_drvdata
> >    nfc: nfc_get_drvdata/nfc_set_drvdata
> >
> >    In the mean time when trying to cleanup the code i found helpers with
> the
> >    exact same purpose in tpm_atmel.h (atmel_get_priv) or tpm_nsc.c
> >    (tpm_nsc_get_priv).
> >
> >    When working on the tpm_vendor_specific cleanup, i came also through
> the
> >    conclusion that moving priv from tpm_vendor_specific to tpm_chip
> structure
> >    would the most
> >    simple and appropriate solution in short term.
> >
> >    ...priv field may be renamed data...
> >    Do you see anything against a serie removing atmel_get_priv and
> >    tpm_nsc_get_priv and with a common helper replacing TPM_VPRIV ?
>
> Yes I do. The current problem is that HW specific stuff lives in the
> framework and not in the drivers for that HW. I would like to see HW
> drivers to use priv for their internal and get rid off
> tpm_vendor_specific completely.
>
> /Jarkko
>
> >    Best Regards
> >    Christophe
> >    2016-03-22 7:20 GMT+01:00 Jarkko Sakkinen
> >    <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>:
> >
> >      On Sun, Mar 20, 2016 at 08:34:36PM +0100, Christophe Ricard wrote:
> >      > Remove TPM_VPRIV macro and replace with tpm_set_vendordata and
> >      > tpm_get_vendordata.
> >
> >      NAK. These unnecessary wrapper functions make code just harder to
> read.
> >      I'd rather accept a patch that would drop TPM_VPRIV and not
> introduce
> >      new clutter.
> >      /Jarkko
> >      > Signed-off-by: Christophe Ricard <christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
> >      > ---
> >      >  drivers/char/tpm/st33zp24/st33zp24.c | 26
> +++++++++++++-------------
> >      >  drivers/char/tpm/tpm.h               | 12 ++++++++++--
> >      >  drivers/char/tpm/tpm_ibmvtpm.c       |  8 ++++----
> >      >  drivers/char/tpm/tpm_tis.c           |  2 +-
> >      >  drivers/char/tpm/xen-tpmfront.c      | 14 +++++++-------
> >      >  5 files changed, 35 insertions(+), 27 deletions(-)
> >      >
> >      > diff --git a/drivers/char/tpm/st33zp24/st33zp24.c
> >      b/drivers/char/tpm/st33zp24/st33zp24.c
> >      > index 9e91ca7..dc2d0f3 100644
> >      > --- a/drivers/char/tpm/st33zp24/st33zp24.c
> >      > +++ b/drivers/char/tpm/st33zp24/st33zp24.c
> >      > @@ -105,7 +105,7 @@ static void st33zp24_cancel(struct tpm_chip
> *chip)
> >      >       struct st33zp24_dev *tpm_dev;
> >      >       u8 data;
> >      >
> >      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> >      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >      >
> >      >       data = TPM_STS_COMMAND_READY;
> >      >       tpm_dev->ops->send(tpm_dev->phy_id, TPM_STS, &data, 1);
> >      > @@ -121,7 +121,7 @@ static u8 st33zp24_status(struct tpm_chip
> *chip)
> >      >       struct st33zp24_dev *tpm_dev;
> >      >       u8 data;
> >      >
> >      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> >      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >      >
> >      >       tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS, &data, 1);
> >      >       return data;
> >      > @@ -138,7 +138,7 @@ static int check_locality(struct tpm_chip
> *chip)
> >      >       u8 data;
> >      >       u8 status;
> >      >
> >      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> >      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >      >
> >      >       status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_ACCESS,
> >      &data, 1);
> >      >       if (status && (data &
> >      > @@ -164,7 +164,7 @@ static int request_locality(struct tpm_chip
> *chip)
> >      >       if (check_locality(chip) == chip->vendor.locality)
> >      >               return chip->vendor.locality;
> >      >
> >      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> >      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >      >
> >      >       data = TPM_ACCESS_REQUEST_USE;
> >      >       ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data,
> >      1);
> >      > @@ -193,7 +193,7 @@ static void release_locality(struct tpm_chip
> >      *chip)
> >      >       struct st33zp24_dev *tpm_dev;
> >      >       u8 data;
> >      >
> >      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> >      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >      >       data = TPM_ACCESS_ACTIVE_LOCALITY;
> >      >
> >      >       tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
> >      > @@ -211,7 +211,7 @@ static int get_burstcount(struct tpm_chip
> *chip)
> >      >       u8 temp;
> >      >       struct st33zp24_dev *tpm_dev;
> >      >
> >      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> >      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >      >
> >      >       stop = jiffies + chip->vendor.timeout_d;
> >      >       do {
> >      > @@ -279,7 +279,7 @@ static int wait_for_stat(struct tpm_chip
> *chip, u8
> >      mask, unsigned long timeout,
> >      >       u8 status;
> >      >       struct st33zp24_dev *tpm_dev;
> >      >
> >      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> >      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >      >
> >      >       /* check current status */
> >      >       status = st33zp24_status(chip);
> >      > @@ -340,7 +340,7 @@ static int recv_data(struct tpm_chip *chip, u8
> >      *buf, size_t count)
> >      >       int size = 0, burstcnt, len, ret;
> >      >       struct st33zp24_dev *tpm_dev;
> >      >
> >      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> >      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >      >
> >      >       while (size < count &&
> >      >              wait_for_stat(chip,
> >      > @@ -372,7 +372,7 @@ 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);
> >      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >      >
> >      >       tpm_dev->intrs++;
> >      >       wake_up_interruptible(&chip->vendor.read_queue);
> >      > @@ -404,7 +404,7 @@ static int st33zp24_send(struct tpm_chip
> *chip,
> >      unsigned char *buf,
> >      >       if (len < TPM_HEADER_SIZE)
> >      >               return -EBUSY;
> >      >
> >      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> >      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >      >
> >      >       ret = request_locality(chip);
> >      >       if (ret < 0)
> >      > @@ -565,7 +565,7 @@ int st33zp24_probe(void *phy_id, const struct
> >      st33zp24_phy_ops *ops,
> >      >       if (!tpm_dev)
> >      >               return -ENOMEM;
> >      >
> >      > -     TPM_VPRIV(chip) = tpm_dev;
> >      > +     tpm_set_vendordata(chip, tpm_dev);
> >      >       tpm_dev->phy_id = phy_id;
> >      >       tpm_dev->ops = ops;
> >      >
> >      > @@ -653,7 +653,7 @@ int st33zp24_pm_suspend(struct device *dev)
> >      >       struct st33zp24_dev *tpm_dev;
> >      >       int ret = 0;
> >      >
> >      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> >      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >      >
> >      >       if (gpio_is_valid(tpm_dev->io_lpcpd))
> >      >               gpio_set_value(tpm_dev->io_lpcpd, 0);
> >      > @@ -675,7 +675,7 @@ int st33zp24_pm_resume(struct device *dev)
> >      >       struct st33zp24_dev *tpm_dev;
> >      >       int ret = 0;
> >      >
> >      > -     tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
> >      > +     tpm_dev = (struct st33zp24_dev *)tpm_get_vendordata(chip);
> >      >
> >      >       if (gpio_is_valid(tpm_dev->io_lpcpd)) {
> >      >               gpio_set_value(tpm_dev->io_lpcpd, 1);
> >      > diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> >      > index 28a0c17..6a973b9 100644
> >      > --- a/drivers/char/tpm/tpm.h
> >      > +++ b/drivers/char/tpm/tpm.h
> >      > @@ -157,8 +157,6 @@ struct tpm_vendor_specific {
> >      >       u16 manufacturer_id;
> >      >  };
> >      >
> >      > -#define TPM_VPRIV(c)     ((c)->vendor.priv)
> >      > -
> >      >  #define TPM_VID_INTEL    0x8086
> >      >  #define TPM_VID_WINBOND  0x1050
> >      >  #define TPM_VID_STM      0x104A
> >      > @@ -203,6 +201,16 @@ struct tpm_chip {
> >      >
> >      >  #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
> >      >
> >      > +static inline void tpm_set_vendordata(struct tpm_chip *chip, void
> >      *data)
> >      > +{
> >      > +     chip->vendor.priv = data;
> >      > +}
> >      > +
> >      > +static inline void *tpm_get_vendordata(struct tpm_chip *chip)
> >      > +{
> >      > +     return chip->vendor.priv;
> >      > +}
> >      > +
> >      >  static inline int tpm_read_index(int base, int index)
> >      >  {
> >      >       outb(index, base);
> >      > diff --git a/drivers/char/tpm/tpm_ibmvtpm.c
> >      b/drivers/char/tpm/tpm_ibmvtpm.c
> >      > index b0a9a9e..c8b1643 100644
> >      > --- a/drivers/char/tpm/tpm_ibmvtpm.c
> >      > +++ b/drivers/char/tpm/tpm_ibmvtpm.c
> >      > @@ -64,7 +64,7 @@ static struct ibmvtpm_dev
> *ibmvtpm_get_data(const
> >      struct device *dev)
> >      >  {
> >      >       struct tpm_chip *chip = dev_get_drvdata(dev);
> >      >       if (chip)
> >      > -             return (struct ibmvtpm_dev *)TPM_VPRIV(chip);
> >      > +             return (struct ibmvtpm_dev
> >      *)tpm_get_vendordata(chip);
> >      >       return NULL;
> >      >  }
> >      >
> >      > @@ -83,7 +83,7 @@ static int tpm_ibmvtpm_recv(struct tpm_chip
> *chip,
> >      u8 *buf, size_t count)
> >      >       u16 len;
> >      >       int sig;
> >      >
> >      > -     ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
> >      > +     ibmvtpm = (struct ibmvtpm_dev *)tpm_get_vendordata(chip);
> >      >
> >      >       if (!ibmvtpm->rtce_buf) {
> >      >               dev_err(ibmvtpm->dev, "ibmvtpm device is not
> >      ready\n");
> >      > @@ -127,7 +127,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip
> *chip,
> >      u8 *buf, size_t count)
> >      >       __be64 *word = (__be64 *)&crq;
> >      >       int rc, sig;
> >      >
> >      > -     ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
> >      > +     ibmvtpm = (struct ibmvtpm_dev *)tpm_get_vendordata(chip);
> >      >
> >      >       if (!ibmvtpm->rtce_buf) {
> >      >               dev_err(ibmvtpm->dev, "ibmvtpm device is not
> >      ready\n");
> >      > @@ -643,7 +643,7 @@ static int tpm_ibmvtpm_probe(struct vio_dev
> >      *vio_dev,
> >      >
> >      >       crq_q->index = 0;
> >      >
> >      > -     TPM_VPRIV(chip) = (void *)ibmvtpm;
> >      > +     tpm_set_vendordata(chip, (void *)ibmvtpm);
> >      >
> >      >       spin_lock_init(&ibmvtpm->rtce_lock);
> >      >
> >      > diff --git a/drivers/char/tpm/tpm_tis.c
> b/drivers/char/tpm/tpm_tis.c
> >      > index eed3bf5..607fa3f 100644
> >      > --- a/drivers/char/tpm/tpm_tis.c
> >      > +++ b/drivers/char/tpm/tpm_tis.c
> >      > @@ -678,7 +678,7 @@ static int tpm_tis_init(struct device *dev,
> struct
> >      tpm_info *tpm_info,
> >      >       if (IS_ERR(chip))
> >      >               return PTR_ERR(chip);
> >      >
> >      > -     chip->vendor.priv = priv;
> >      > +     tpm_set_vendordata(chip, priv);
> >      >  #ifdef CONFIG_ACPI
> >      >       chip->acpi_dev_handle = acpi_dev_handle;
> >      >  #endif
> >      > diff --git a/drivers/char/tpm/xen-tpmfront.c
> >      b/drivers/char/tpm/xen-tpmfront.c
> >      > index 3111f27..c472fd8 100644
> >      > --- a/drivers/char/tpm/xen-tpmfront.c
> >      > +++ b/drivers/char/tpm/xen-tpmfront.c
> >      > @@ -39,7 +39,7 @@ enum status_bits {
> >      >
> >      >  static u8 vtpm_status(struct tpm_chip *chip)
> >      >  {
> >      > -     struct tpm_private *priv = TPM_VPRIV(chip);
> >      > +     struct tpm_private *priv = tpm_get_vendordata(chip);
> >      >       switch (priv->shr->state) {
> >      >       case VTPM_STATE_IDLE:
> >      >               return VTPM_STATUS_IDLE | VTPM_STATUS_CANCELED;
> >      > @@ -60,7 +60,7 @@ static bool vtpm_req_canceled(struct tpm_chip
> *chip,
> >      u8 status)
> >      >
> >      >  static void vtpm_cancel(struct tpm_chip *chip)
> >      >  {
> >      > -     struct tpm_private *priv = TPM_VPRIV(chip);
> >      > +     struct tpm_private *priv = tpm_get_vendordata(chip);
> >      >       priv->shr->state = VTPM_STATE_CANCEL;
> >      >       wmb();
> >      >       notify_remote_via_evtchn(priv->evtchn);
> >      > @@ -73,7 +73,7 @@ static unsigned int shr_data_offset(struct
> >      vtpm_shared_page *shr)
> >      >
> >      >  static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t
> count)
> >      >  {
> >      > -     struct tpm_private *priv = TPM_VPRIV(chip);
> >      > +     struct tpm_private *priv = tpm_get_vendordata(chip);
> >      >       struct vtpm_shared_page *shr = priv->shr;
> >      >       unsigned int offset = shr_data_offset(shr);
> >      >
> >      > @@ -115,7 +115,7 @@ static int vtpm_send(struct tpm_chip *chip, u8
> >      *buf, size_t count)
> >      >
> >      >  static int vtpm_recv(struct tpm_chip *chip, u8 *buf, size_t
> count)
> >      >  {
> >      > -     struct tpm_private *priv = TPM_VPRIV(chip);
> >      > +     struct tpm_private *priv = tpm_get_vendordata(chip);
> >      >       struct vtpm_shared_page *shr = priv->shr;
> >      >       unsigned int offset = shr_data_offset(shr);
> >      >       size_t length = shr->length;
> >      > @@ -182,7 +182,7 @@ static int setup_chip(struct device *dev,
> struct
> >      tpm_private *priv)
> >      >       init_waitqueue_head(&chip->vendor.read_queue);
> >      >
> >      >       priv->chip = chip;
> >      > -     TPM_VPRIV(chip) = priv;
> >      > +     tpm_set_vendordata(chip, priv);
> >      >
> >      >       return 0;
> >      >  }
> >      > @@ -318,10 +318,10 @@ static int tpmfront_probe(struct
> xenbus_device
> >      *dev,
> >      >  static int tpmfront_remove(struct xenbus_device *dev)
> >      >  {
> >      >       struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
> >      > -     struct tpm_private *priv = TPM_VPRIV(chip);
> >      > +     struct tpm_private *priv = tpm_get_vendordata(chip);
> >      >       tpm_chip_unregister(chip);
> >      >       ring_free(priv);
> >      > -     TPM_VPRIV(chip) = NULL;
> >      > +     tpm_set_vendordata(chip, NULL);
> >      >       return 0;
> >      >  }
> >      >
> >      > --
> >      > 2.5.0
> >      >
>

[-- Attachment #1.2: Type: text/html, Size: 20912 bytes --]

[-- Attachment #2: Type: text/plain, Size: 291 bytes --]

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

[-- Attachment #3: Type: text/plain, Size: 192 bytes --]

_______________________________________________
tpmdd-devel mailing list
tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/tpmdd-devel

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 05/12] tpm: Add tpm_set_vendordata and tpm_get_vendordata
       [not found]                     ` <CALD+uuwVG_84dY4rCOjecZXxS4LZoE+Kh=CyhmVwyT2U0bAMrg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2016-03-24 16:18                       ` Jason Gunthorpe
       [not found]                         ` <20160324161819.GA5263-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
  0 siblings, 1 reply; 39+ messages in thread
From: Jason Gunthorpe @ 2016-03-24 16:18 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: Jean-Luc BLANC, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Christophe RICARD,
	Benoit HOUYERE

On Thu, Mar 24, 2016 at 02:30:24PM +0100, Christophe Ricard wrote:
> Hi Jarkko,
> 
> I am currently working at removing this TPM_VPRIV and priv field as requested
> previously.
> As pointed by you or Jason, i succeeded to go the dev_get_drvdata way :).

We may need another patch or two to allow that, I have an ugly feeling
the chip->drvdata is being used for something

Jason

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 05/12] tpm: Add tpm_set_vendordata and tpm_get_vendordata
       [not found]                         ` <20160324161819.GA5263-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
@ 2016-03-24 16:31                           ` Christophe Ricard
       [not found]                             ` <CALD+uux0-nbwJfsHFHqPrZwWt=vEy73oi_djNrrY5QeiWwCq9A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  0 siblings, 1 reply; 39+ messages in thread
From: Christophe Ricard @ 2016-03-24 16:31 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Jean-Luc BLANC, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Christophe RICARD,
	Benoit HOUYERE


[-- Attachment #1.1: Type: text/plain, Size: 1030 bytes --]

I got confused like you are but when looking a little bit better at the
code i think we have 2 differents "struct device" available on a tpm driver.
One is coming from the physical layer driver (aka: client->dev, spi->dev,
pdev->dev) and the other one from chip->dev which is initialized in
tpm_chip_alloc.
As a consequence, a quick trick allows to set data to physical layer driver
or to the tpm_chip device.

I haven't seen any place where this is already used for anything. Do you
confirm ?

Best Regards
Christophe

2016-03-24 17:18 GMT+01:00 Jason Gunthorpe <jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
:

> On Thu, Mar 24, 2016 at 02:30:24PM +0100, Christophe Ricard wrote:
> > Hi Jarkko,
> >
> > I am currently working at removing this TPM_VPRIV and priv field as
> requested
> > previously.
> > As pointed by you or Jason, i succeeded to go the dev_get_drvdata way :).
>
> We may need another patch or two to allow that, I have an ugly feeling
> the chip->drvdata is being used for something
>
> Jason
>

[-- Attachment #1.2: Type: text/html, Size: 1620 bytes --]

[-- Attachment #2: Type: text/plain, Size: 291 bytes --]

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

[-- Attachment #3: Type: text/plain, Size: 192 bytes --]

_______________________________________________
tpmdd-devel mailing list
tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/tpmdd-devel

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 05/12] tpm: Add tpm_set_vendordata and tpm_get_vendordata
       [not found]                             ` <CALD+uux0-nbwJfsHFHqPrZwWt=vEy73oi_djNrrY5QeiWwCq9A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2016-03-24 17:10                               ` Jason Gunthorpe
       [not found]                                 ` <20160324171032.GA27978-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
  0 siblings, 1 reply; 39+ messages in thread
From: Jason Gunthorpe @ 2016-03-24 17:10 UTC (permalink / raw)
  To: Christophe Ricard
  Cc: Jean-Luc BLANC, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Christophe RICARD,
	Benoit HOUYERE

On Thu, Mar 24, 2016 at 05:31:21PM +0100, Christophe Ricard wrote:
>    I got confused like you are but when looking a little bit better at the
>    code i think we have 2 differents "struct device" available on a tpm
>    driver.
>    One is coming from the physical layer driver (aka: client->dev,
>    spi->dev, pdev->dev) and the other one from chip->dev which is
>    initialized in tpm_chip_alloc.

Yes, client->dev's drvdata (aka chip->dev.parent) should point to the
chip. In an ideal world the TPM core will never touch this, but we are
not quite there yet, sysfs in particular is broken.

chip->dev's drvdata could/should point to the driver's priv, that
would make sense. With Jarkko's tree today that is OK.

But Stefan's vtpm driver adds a use:

 https://github.com/stefanberger/linux/commit/3ab4e3aabf50137068e2807910e5f867668b4e23

Which is an ugly hacky thing..

So, if you are planning a tpm_get_drvdata or whatever then we should
probably patch vtpm to put priv back in or patch vtpm to not need that
hack.

Jason

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

^ permalink raw reply	[flat|nested] 39+ messages in thread

* Re: [PATCH 05/12] tpm: Add tpm_set_vendordata and tpm_get_vendordata
       [not found]                                 ` <20160324171032.GA27978-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
@ 2016-03-24 23:04                                   ` Christophe Ricard
  0 siblings, 0 replies; 39+ messages in thread
From: Christophe Ricard @ 2016-03-24 23:04 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Jean-Luc BLANC, ashley-fm2HMyfA2y6tG0bUXCXiUA,
	tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Christophe RICARD,
	Benoit HOUYERE


[-- Attachment #1.1: Type: text/plain, Size: 1742 bytes --]



On 24/03/2016 18:10, Jason Gunthorpe wrote:
> On Thu, Mar 24, 2016 at 05:31:21PM +0100, Christophe Ricard wrote:
>>     I got confused like you are but when looking a little bit better at the
>>     code i think we have 2 differents "struct device" available on a tpm
>>     driver.
>>     One is coming from the physical layer driver (aka: client->dev,
>>     spi->dev, pdev->dev) and the other one from chip->dev which is
>>     initialized in tpm_chip_alloc.
> Yes, client->dev's drvdata (aka chip->dev.parent) should point to the
> chip. In an ideal world the TPM core will never touch this, but we are
> not quite there yet, sysfs in particular is broken.
>
> chip->dev's drvdata could/should point to the driver's priv, that
> would make sense. With Jarkko's tree today that is OK.
>
> But Stefan's vtpm driver adds a use:
>
>   https://github.com/stefanberger/linux/commit/3ab4e3aabf50137068e2807910e5f867668b4e23
>
> Which is an ugly hacky thing..
I ran through the changes using client->dev's drvdata pointing to the 
chip and
&chip->dev's drvdata pointing to the driver's priv.
I have looked to stefanberger githubs and i am really sceptical about 
the purpose
of doing dev_set_drvdata(&chip->dev, chip); in tpm_sysfs_add_device.
I haven't seen any dev_get_drvdata(&chip->dev) in the tree even on top 
of the history. Did i overlooked at it ?
Shouldn't dev_set_drvdata(&chip->dev, chip);  in tpm_sysfs_add_device be 
removed ?

I plan to release the next serie about tpm_vendor_specific cleanup by 
tomorrow at least for further discussion :).
> So, if you are planning a tpm_get_drvdata or whatever then we should
> probably patch vtpm to put priv back in or patch vtpm to not need that
> hack.
>
> Jason
Best Regards
Christophe

[-- Attachment #1.2: Type: text/html, Size: 3111 bytes --]

[-- Attachment #2: Type: text/plain, Size: 291 bytes --]

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140

[-- Attachment #3: Type: text/plain, Size: 192 bytes --]

_______________________________________________
tpmdd-devel mailing list
tpmdd-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/tpmdd-devel

^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2016-03-24 23:04 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-20 19:34 [PATCH 00/12] Few minnor fixes, rework of tpm_tis to support tcg spi and i2c Christophe Ricard
     [not found] ` <1458502483-16887-1-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2016-03-20 19:34   ` [PATCH 01/12] tpm/st33zp24/i2c: Drop two useless checks in ACPI probe path Christophe Ricard
2016-03-20 19:34   ` [PATCH 02/12] tpm/st33zp24/spi: " Christophe Ricard
     [not found]     ` <1458502483-16887-3-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2016-03-22  5:10       ` Jarkko Sakkinen
2016-03-20 19:34   ` [PATCH 03/12] tpm: Add include guards in tpm.h Christophe Ricard
     [not found]     ` <1458502483-16887-4-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2016-03-22  5:13       ` Jarkko Sakkinen
2016-03-20 19:34   ` [PATCH 04/12] tpm/st33zp24: Remove unneeded tpm_reg in get_burstcount Christophe Ricard
     [not found]     ` <1458502483-16887-5-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2016-03-22  6:16       ` Jarkko Sakkinen
     [not found]         ` <20160322061650.GA4058-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2016-03-22  6:21           ` Christophe Ricard
2016-03-20 19:34   ` [PATCH 05/12] tpm: Add tpm_set_vendordata and tpm_get_vendordata Christophe Ricard
     [not found]     ` <1458502483-16887-6-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2016-03-22  6:20       ` Jarkko Sakkinen
     [not found]         ` <20160322062001.GB4058-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2016-03-22 15:58           ` Jason Gunthorpe
     [not found]             ` <20160322155824.GA25600-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2016-03-22 16:00               ` Christophe Ricard
2016-03-23 13:11           ` Christophe Ricard
     [not found]             ` <CALD+uuxj2NHd0-LpDZpnfkfMHwY6ke0FPPqmR0FKzrC4BJmFNQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-03-23 16:48               ` Jason Gunthorpe
2016-03-24 13:27               ` Jarkko Sakkinen
     [not found]                 ` <20160324132732.GF8452-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2016-03-24 13:30                   ` Christophe Ricard
     [not found]                     ` <CALD+uuwVG_84dY4rCOjecZXxS4LZoE+Kh=CyhmVwyT2U0bAMrg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-03-24 16:18                       ` Jason Gunthorpe
     [not found]                         ` <20160324161819.GA5263-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2016-03-24 16:31                           ` Christophe Ricard
     [not found]                             ` <CALD+uux0-nbwJfsHFHqPrZwWt=vEy73oi_djNrrY5QeiWwCq9A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-03-24 17:10                               ` Jason Gunthorpe
     [not found]                                 ` <20160324171032.GA27978-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2016-03-24 23:04                                   ` Christophe Ricard
2016-03-20 19:34   ` [PATCH 06/12] devicetree: Add infineon to vendor-prefix.txt Christophe Ricard
2016-03-20 19:34   ` [PATCH 07/12] devicetree: Add Trusted Computing Group " Christophe Ricard
2016-03-20 19:34   ` [PATCH 08/12] tpm/tpm_tis: Split tpm_tis driver into a core and TCG TIS compliant phy Christophe Ricard
     [not found]     ` <1458502483-16887-9-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2016-03-21  1:32       ` Jason Gunthorpe
     [not found]         ` <20160321013243.GA9417-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2016-03-21 22:35           ` Christophe Ricard
     [not found]             ` <56F0774F.7040707-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2016-03-21 23:26               ` Jason Gunthorpe
2016-03-22  6:23       ` Jarkko Sakkinen
2016-03-20 19:34   ` [PATCH 09/12] tpm/tpm_tis: Rework interrupt management for phy compatibility Christophe Ricard
     [not found]     ` <1458502483-16887-10-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2016-03-21  1:37       ` Jason Gunthorpe
     [not found]         ` <20160321013722.GB9417-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2016-03-21 17:45           ` Christophe Ricard
2016-03-20 19:34   ` [PATCH 10/12] tpm/tpm_tis_spi: Add support for spi phy Christophe Ricard
2016-03-20 19:34   ` [PATCH 11/12] tpm: Add check_data handle to tpm_class_ops in order to check data integrity Christophe Ricard
     [not found]     ` <1458502483-16887-12-git-send-email-christophe-h.ricard-qxv4g6HH51o@public.gmane.org>
2016-03-21  1:39       ` Jason Gunthorpe
     [not found]         ` <20160321013933.GC9417-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2016-03-21 17:44           ` Christophe Ricard
2016-03-20 19:34   ` [PATCH 12/12] tpm/tpm_tis_i2c: Add support for i2c phy Christophe Ricard
2016-03-20 21:59   ` [PATCH 00/12] Few minnor fixes, rework of tpm_tis to support tcg spi and i2c Peter Huewe
2016-03-21 11:13   ` Jarkko Sakkinen
2016-03-22  5:17   ` Jarkko Sakkinen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.