linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
@ 2012-11-19 22:15 Mathias Leblanc
  2012-11-19 22:15 ` [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 2.6 Mathias Leblanc
  2012-11-26 17:46 ` [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x Kent Yoder
  0 siblings, 2 replies; 33+ messages in thread
From: Mathias Leblanc @ 2012-11-19 22:15 UTC (permalink / raw)
  To: Kent Yoder, Rajiv Andrade, Marcel Selhorst, Sirrix AG,
	tpmdd-devel, Debora Velarde
  Cc: linux-kernel, Jean-Luc Blanc, Mathias Leblanc

 * STMicroelectronics version 1.2.0, Copyright (C) 2010
 * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
 * This is free software, and you are welcome to redistribute it
 * under certain conditions.

This is the driver for TPM chip from ST Microelectronics.

If you have a TPM security chip from STMicroelectronics working with
an I2C, in menuconfig or .config choose the tpm driver on
device --> tpm and activate the protocol of your choice before compiling
the kernel.
The driver will be accessible from within Linux.

Tested on linux x86/x64, beagleboard REV B & XM REV C and CHROMIUM OS
on kernel 3.x.x

Signed-off-by: Mathias Leblanc <mathias.leblanc@st.com>
---
 drivers/char/tpm/tpm_stm_st33_i2c.c  |  903 ++++++++++++++++++++++++++++++++++
 drivers/char/tpm/tpm_stm_st33_i2c.h  |   81 +++
 include/linux/i2c/tpm_stm_st33_i2c.h |   47 ++
 3 files changed, 1031 insertions(+)
 create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.c
 create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.h
 create mode 100644 include/linux/i2c/tpm_stm_st33_i2c.h

diff --git a/drivers/char/tpm/tpm_stm_st33_i2c.c b/drivers/char/tpm/tpm_stm_st33_i2c.c
new file mode 100644
index 0000000..3ec6ae9
--- /dev/null
+++ b/drivers/char/tpm/tpm_stm_st33_i2c.c
@@ -0,0 +1,903 @@
+/*
+ * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
+ * Copyright (C) 2009, 2010  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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * STMicroelectronics version 1.2.0, Copyright (C) 2010
+ * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
+ * This is free software, and you are welcome to redistribute it
+ * under certain conditions.
+ *
+ * @Author: Christophe RICARD tpmsupport@st.com
+ *
+ * @File: tpm_stm_st33_i2c.c
+ *
+ * @Synopsis:
+ *	09/15/2010:	First shot driver tpm_tis driver for
+			 lpc is used as model.
+ */
+
+#include <linux/i2c/tpm_stm_st33_i2c.h>
+
+#include "tpm_stm_st33_i2c.h"
+
+enum stm33zp24_access {
+	TPM_ACCESS_VALID = 0x80,
+	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
+	TPM_ACCESS_REQUEST_PENDING = 0x04,
+	TPM_ACCESS_REQUEST_USE = 0x02,
+};
+
+enum stm33zp24_status {
+	TPM_STS_VALID = 0x80,
+	TPM_STS_COMMAND_READY = 0x40,
+	TPM_STS_GO = 0x20,
+	TPM_STS_DATA_AVAIL = 0x10,
+	TPM_STS_DATA_EXPECT = 0x08,
+};
+
+enum stm33zp24_int_flags {
+	TPM_GLOBAL_INT_ENABLE = 0x80,
+	TPM_INTF_CMD_READY_INT = 0x080,
+	TPM_INTF_FIFO_AVALAIBLE_INT = 0x040,
+	TPM_INTF_WAKE_UP_READY_INT = 0x020,
+	TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
+	TPM_INTF_STS_VALID_INT = 0x002,
+	TPM_INTF_DATA_AVAIL_INT = 0x001,
+};
+
+enum tis_defaults {
+	TIS_SHORT_TIMEOUT = 750,
+	TIS_LONG_TIMEOUT = 2000,
+};
+
+/*
+ * write8_reg
+ * Send byte to the TIS register according to the ST33ZP24 I2C protocol.
+ * @param: tpm_register, the tpm tis register where the data should be written
+ * @param: tpm_data, the tpm_data to write inside the tpm_register
+ * @param: tpm_size, The length of the data
+ * @return: Returns negative errno, or else the number of bytes written.
+ */
+static int write8_reg(struct i2c_client *client, u8 tpm_register,
+		      u8 *tpm_data, u16 tpm_size)
+{
+	u8 data;
+	int value = 0;
+	struct st33zp24_platform_data *pin_infos;
+
+	pin_infos = client->dev.platform_data;
+
+	data = tpm_register;
+	memcpy(pin_infos->tpm_i2c_buffer[0], &data, sizeof(data));
+	memcpy(pin_infos->tpm_i2c_buffer[0] + 1, tpm_data, tpm_size);
+	value = i2c_master_send(client, pin_infos->tpm_i2c_buffer[0],
+				tpm_size + 1);
+	return value;
+} /* write8_reg() */
+
+/*
+ * read8_reg
+ * Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
+ * @param: tpm_register, the tpm tis register where the data should be read
+ * @param: tpm_data, the TPM response
+ * @param: tpm_size, tpm TPM response size to read.
+ * @return: number of byte read successfully: should be one if success.
+ */
+static int read8_reg(struct i2c_client *client, u8 tpm_register,
+		    u8 *tpm_data, int tpm_size)
+{
+	u8 status = 0;
+	u8 data;
+	struct st33zp24_platform_data *pin_infos;
+
+	pin_infos = client->dev.platform_data;
+
+	data = TPM_DUMMY_BYTE;
+	status = write8_reg(client, tpm_register, &data, 1);
+	if (status == 2)
+		status = i2c_master_recv(client, tpm_data, tpm_size);
+	return status;
+} /* read8_reg() */
+
+/*
+ * I2C_WRITE_DATA
+ * Send byte to the TIS register according to the ST33ZP24 I2C protocol.
+ * @param: client, the chip description
+ * @param: tpm_register, the tpm tis register where the data should be written
+ * @param: tpm_data, the tpm_data to write inside the tpm_register
+ * @param: tpm_size, The length of the data
+ * @return: number of byte written successfully: should be one if success.
+ */
+#define I2C_WRITE_DATA(client, tpm_register, tpm_data, tpm_size) \
+	(write8_reg(client, tpm_register | \
+	TPM_WRITE_DIRECTION, tpm_data, tpm_size))
+
+/*
+ * I2C_READ_DATA
+ * Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
+ * @param: tpm, the chip description
+ * @param: tpm_register, the tpm tis register where the data should be read
+ * @param: tpm_data, the TPM response
+ * @param: tpm_size, tpm TPM response size to read.
+ * @return: number of byte read successfully: should be one if success.
+ */
+#define I2C_READ_DATA(client, tpm_register, tpm_data, tpm_size) \
+	(read8_reg(client, tpm_register, tpm_data, tpm_size))
+
+/*
+ * clear_interruption
+ * clear the TPM interrupt register.
+ * @param: tpm, the chip description
+ */
+static void clear_interruption(struct i2c_client *client)
+{
+	u8 interrupt;
+	I2C_READ_DATA(client, TPM_INT_STATUS, &interrupt, 1);
+	I2C_WRITE_DATA(client, TPM_INT_STATUS, &interrupt, 1);
+	I2C_READ_DATA(client, TPM_INT_STATUS, &interrupt, 1);
+} /* clear_interruption() */
+
+/*
+ * _wait_for_interrupt_serirq_timeout
+ * @param: tpm, the chip description
+ * @param: timeout, the timeout of the interrupt
+ * @return: the status of the interruption.
+ */
+static long _wait_for_interrupt_serirq_timeout(struct tpm_chip *chip,
+						unsigned long timeout)
+{
+	long status;
+	struct i2c_client *client;
+	struct st33zp24_platform_data *pin_infos;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+	pin_infos = client->dev.platform_data;
+
+	status = wait_for_completion_interruptible_timeout(
+					&pin_infos->irq_detection,
+						timeout);
+	if (status > 0)
+		enable_irq(gpio_to_irq(pin_infos->io_serirq));
+	gpio_direction_input(pin_infos->io_serirq);
+
+	return status;
+} /* wait_for_interrupt_serirq_timeout() */
+
+int wait_for_serirq_timeout(struct tpm_chip *chip, bool condition,
+				 unsigned long timeout)
+{
+	int status = 2;
+	struct i2c_client *client;
+	struct st33zp24_platform_data *pin_infos;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+	pin_infos = client->dev.platform_data;
+
+	status = _wait_for_interrupt_serirq_timeout(chip, timeout);
+	if (!status) {
+		status = -EBUSY;
+	} else{
+		clear_interruption(client);
+		if (condition)
+			status = 1;
+	}
+	return status;
+}
+
+/*
+ * tpm_stm_i2c_cancel, cancel is not implemented.
+ * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h
+ */
+static void tpm_stm_i2c_cancel(struct tpm_chip *chip)
+{
+	struct i2c_client *client;
+	u8 data;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+
+	data = TPM_STS_COMMAND_READY;
+	I2C_WRITE_DATA(client, TPM_STS, &data, 1);
+	if (chip->vendor.irq)
+		wait_for_serirq_timeout(chip, 1, chip->vendor.timeout_a);
+}	/* tpm_stm_i2c_cancel() */
+
+/*
+ * tpm_stm_spi_status return the TPM_STS register
+ * @param: chip, the tpm chip description
+ * @return: the TPM_STS register value.
+ */
+static u8 tpm_stm_i2c_status(struct tpm_chip *chip)
+{
+	struct i2c_client *client;
+	u8 data;
+	client = (struct i2c_client *) chip->vendor.iobase;
+
+	I2C_READ_DATA(client, TPM_STS, &data, 1);
+	return data;
+}				/* tpm_stm_i2c_status() */
+
+
+/*
+ * check_locality if the locality is active
+ * @param: chip, the tpm chip description
+ * @return: the active locality or -EACCESS.
+ */
+static int check_locality(struct tpm_chip *chip)
+{
+	struct i2c_client *client;
+	u8 data;
+	u8 status;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+
+	status = I2C_READ_DATA(client, TPM_ACCESS, &data, 1);
+	if (status && (data &
+		(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
+		(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
+		return chip->vendor.locality;
+
+	return -EACCES;
+
+} /* check_locality() */
+
+/*
+ * request_locality request the TPM locality
+ * @param: chip, the chip description
+ * @return: the active locality or EACCESS.
+ */
+static int request_locality(struct tpm_chip *chip)
+{
+	unsigned long stop;
+	long rc;
+	struct i2c_client *client;
+	u8 data;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+
+	if (check_locality(chip) == chip->vendor.locality)
+		return chip->vendor.locality;
+
+	data = TPM_ACCESS_REQUEST_USE;
+	rc = I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1);
+	if (rc < 0)
+		goto end;
+
+	if (chip->vendor.irq) {
+		rc = wait_for_serirq_timeout(chip, (check_locality
+						       (chip) >= 0),
+						      chip->vendor.timeout_a);
+		if (rc > 0)
+			return chip->vendor.locality;
+	} else{
+		stop = jiffies + chip->vendor.timeout_a;
+		do {
+			if (check_locality(chip) >= 0)
+				return chip->vendor.locality;
+			msleep(TPM_TIMEOUT);
+		} while (time_before(jiffies, stop));
+	}
+	rc = -EACCES;
+end:
+	return rc;
+} /* request_locality() */
+
+/*
+ * release_locality release the active locality
+ * @param: chip, the tpm chip description.
+ */
+static void release_locality(struct tpm_chip *chip)
+{
+	struct i2c_client *client;
+	u8 data;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+	data = TPM_ACCESS_ACTIVE_LOCALITY;
+
+	I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1);
+}
+
+/*
+ * get_burstcount return the burstcount address 0x19 0x1A
+ * @param: chip, the chip description
+ * return: the burstcount.
+ */
+static int get_burstcount(struct tpm_chip *chip)
+{
+	unsigned long stop;
+	int burstcnt, status;
+	u8 tpm_reg, temp;
+
+	struct i2c_client *client = (struct i2c_client *) chip->vendor.iobase;
+
+	stop = jiffies + chip->vendor.timeout_d;
+	do {
+		tpm_reg = TPM_STS + 1;
+		status = I2C_READ_DATA(client, tpm_reg, &temp, 1);
+		if (status < 0)
+			goto end;
+
+		tpm_reg = tpm_reg + 1;
+		burstcnt = temp;
+		status = I2C_READ_DATA(client, tpm_reg, &temp, 1);
+		if (status < 0)
+			goto end;
+
+		burstcnt |= temp << 8;
+		if (burstcnt)
+			return burstcnt;
+		msleep(TPM_TIMEOUT);
+	} while (time_before(jiffies, stop));
+
+end:
+	return -EBUSY;
+} /* get_burstcount() */
+
+/*
+ * wait_for_stat wait for a TPM_STS value
+ * @param: chip, the tpm chip description
+ * @param: mask, the value mask to wait
+ * @param: timeout, the timeout
+ * @param: queue, the wait queue.
+ * @return: the tpm status, 0 if success, -ETIME if timeout is reached.
+ */
+static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
+			 wait_queue_head_t *queue)
+{
+	unsigned long stop;
+	long rc;
+	u8 status;
+
+	 if (chip->vendor.irq) {
+		rc = wait_for_serirq_timeout(chip, ((tpm_stm_i2c_status
+							(chip) & mask) ==
+						       mask), timeout);
+		if (rc > 0)
+			return 0;
+	} else{
+		stop = jiffies + timeout;
+		do {
+			msleep(TPM_TIMEOUT);
+			status = tpm_stm_i2c_status(chip);
+			if ((status & mask) == mask)
+				return 0;
+		} while (time_before(jiffies, stop));
+	}
+	return -ETIME;
+} /* wait_for_stat() */
+
+/*
+ * recv_data receive data
+ * @param: chip, the tpm chip description
+ * @param: buf, the buffer where the data are received
+ * @param: count, the number of data to receive
+ * @return: the number of bytes read from TPM FIFO.
+ */
+static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	int size = 0, burstcnt, len;
+	struct i2c_client *client;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+
+	while (size < count &&
+	       wait_for_stat(chip,
+			     TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+			     chip->vendor.timeout_c,
+			     &chip->vendor.read_queue)
+	       == 0) {
+		burstcnt = get_burstcount(chip);
+		len = min_t(int, burstcnt, count - size);
+		I2C_READ_DATA(client, TPM_DATA_FIFO, buf + size, len);
+		size += len;
+	}
+	return size;
+}
+
+/*
+ * tpm_ioserirq_handler the serirq irq handler
+ * @param: irq, the tpm chip description
+ * @param: dev_id, the description of the chip
+ * @return: the status of the handler.
+ */
+static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id)
+{
+	struct tpm_chip *chip = dev_id;
+	struct i2c_client *client;
+	struct st33zp24_platform_data *pin_infos;
+
+	disable_irq_nosync(irq);
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+	pin_infos = client->dev.platform_data;
+
+	complete(&pin_infos->irq_detection);
+	return IRQ_HANDLED;
+} /* tpm_ioserirq_handler() */
+
+
+/*
+ * tpm_stm_i2c_send send TPM commands through the I2C bus.
+ *
+ * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h
+ * @param: buf,	the buffer to send.
+ * @param: count, the number of bytes to send.
+ * @return: In case of success the number of bytes sent.
+ *			In other case, a < 0 value describing the issue.
+ */
+static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
+			    size_t len)
+{
+	u32 ret = 0, ordinal,
+	    status,
+	    burstcnt = 0, i, size;
+	u8 data;
+	struct i2c_client *client;
+	struct st33zp24_platform_data *pin_infos;
+
+	if (chip == NULL)
+		return -EBUSY;
+	if (len < TPM_HEADER_SIZE)
+		return -EBUSY;
+
+	client = (struct i2c_client *)chip->vendor.iobase;
+	pin_infos = client->dev.platform_data;
+
+	ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
+
+	client->flags = 0;
+
+	ret = request_locality(chip);
+	if (ret < 0)
+		return ret;
+
+	status = tpm_stm_i2c_status(chip);
+	if ((status & TPM_STS_COMMAND_READY) == 0) {
+		tpm_stm_i2c_cancel(chip);
+		if (wait_for_stat
+		    (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
+		     &chip->vendor.int_queue) < 0) {
+			ret = -ETIME;
+			goto out_err;
+		}
+	}
+
+	for (i = 0 ; i < len - 1 ;) {
+		burstcnt = get_burstcount(chip);
+		size = min_t(int, len - i - 1, burstcnt);
+		ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf, size);
+		if (ret < 0)
+			goto out_err;
+
+		i += size;
+	}
+
+	status = tpm_stm_i2c_status(chip);
+	if ((status & TPM_STS_DATA_EXPECT) == 0) {
+		ret = -EIO;
+		goto out_err;
+	}
+
+	ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf + len - 1, 1);
+	if (ret < 0)
+		goto out_err;
+
+	status = tpm_stm_i2c_status(chip);
+	if ((status & TPM_STS_DATA_EXPECT) != 0) {
+		ret = -EIO;
+		goto out_err;
+	}
+
+	data = TPM_STS_GO;
+	I2C_WRITE_DATA(client, TPM_STS, &data, 1);
+
+	return len;
+out_err:
+	tpm_stm_i2c_cancel(chip);
+	release_locality(chip);
+	return ret;
+}
+
+/*
+ * tpm_stm_i2c_recv received TPM response through the I2C bus.
+ * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h.
+ * @param: buf,	the buffer to store datas.
+ * @param: count, the number of bytes to send.
+ * @return: In case of success the number of bytes received.
+ *		In other case, a < 0 value describing the issue.
+ */
+static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
+			    size_t count)
+{
+	int size = 0;
+	int expected;
+
+	struct i2c_client *client;
+	struct st33zp24_platform_data *pin_infos;
+
+	client = (struct i2c_client *)chip->vendor.iobase;
+	pin_infos = client->dev.platform_data;
+
+
+	if (chip == NULL)
+		return -EBUSY;
+
+	if (count < TPM_HEADER_SIZE) {
+		size = -EIO;
+		goto out;
+	}
+
+	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;
+	}
+
+out:
+	chip->vendor.cancel(chip);
+	release_locality(chip);
+	return size;
+}
+
+static const struct file_operations tpm_st33_i2c_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.read = tpm_read,
+	.write = tpm_write,
+	.open = tpm_open,
+	.release = tpm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute *stm_tpm_attrs[] = {
+	&dev_attr_pubek.attr,
+	&dev_attr_pcrs.attr,
+	&dev_attr_enabled.attr,
+	&dev_attr_active.attr,
+	&dev_attr_owned.attr,
+	&dev_attr_temp_deactivated.attr,
+	&dev_attr_caps.attr,
+	&dev_attr_cancel.attr, NULL,
+};
+
+static struct attribute_group stm_tpm_attr_grp = {
+	.attrs = stm_tpm_attrs
+};
+
+static struct tpm_vendor_specific st_i2c_tpm = {
+	.send = tpm_stm_i2c_send,
+	.recv = tpm_stm_i2c_recv,
+	.cancel = tpm_stm_i2c_cancel,
+	.status = tpm_stm_i2c_status,
+	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_canceled = TPM_STS_COMMAND_READY,
+	.attr_group = &stm_tpm_attr_grp,
+	.miscdev = {.fops = &tpm_st33_i2c_fops,},
+};
+
+static int interrupts ;
+module_param(interrupts, int, 0444);
+MODULE_PARM_DESC(interrupts, "Enable interrupts");
+
+static int power_mgt = 1;
+module_param(power_mgt, int, 0444);
+MODULE_PARM_DESC(power_mgt, "Power Management");
+
+/*
+ * tpm_st33_i2c_probe initialize the TPM device
+ * @param: client, the i2c_client drescription (TPM I2C description).
+ * @param: id, the i2c_device_id struct.
+ * @return: 0 in case of success.
+ *	 -1 in other case.
+ */
+static int
+tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	u32 err;
+	u8 intmask;
+	struct tpm_chip *chip;
+	struct st33zp24_platform_data *platform_data;
+
+	err = 0;
+
+	if (client == NULL) {
+		dev_info(&client->dev, "client is NULL. exiting.\n");
+		err = -ENODEV;
+		goto end;
+	}
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_info(&client->dev, "client not i2c capable\n");
+		err = -ENODEV;
+		goto end;
+	}
+
+	chip = tpm_register_hardware(&client->dev, &st_i2c_tpm);
+	if (!chip) {
+		dev_info(&client->dev, "fail chip\n");
+		err = -ENODEV;
+		goto end;
+	}
+
+	platform_data = client->dev.platform_data;
+	platform_data->tpm_i2c_buffer[0] =
+	    kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+	if (platform_data->tpm_i2c_buffer[0] == NULL) {
+		err = -ENOMEM;
+		goto _tpm_clean_answer;
+	}
+	platform_data->tpm_i2c_buffer[1] =
+	    kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+	if (platform_data->tpm_i2c_buffer[1] == NULL) {
+		err = -ENOMEM;
+		goto _tpm_clean_response;
+	}
+
+	chip->vendor.iobase = client;
+
+	chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
+	chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+
+	chip->vendor.locality = LOCALITY0;
+
+	if (power_mgt) {
+		err = gpio_request(platform_data->io_lpcpd, "TPM IO_LPCPD");
+		if (err)
+			goto _gpio_init1;
+		gpio_set_value(platform_data->io_lpcpd, 1);
+	}
+
+	if (interrupts) {
+		init_completion(&platform_data->irq_detection);
+		if (request_locality(chip) != LOCALITY0) {
+			err = -ENODEV;
+			goto _tpm_clean_response;
+		}
+		err = gpio_request(platform_data->io_serirq, "TPM IO_SERIRQ");
+		if (err)
+			goto _gpio_init2;
+
+		clear_interruption(client);
+		err = request_irq(gpio_to_irq(platform_data->io_serirq),
+				&tpm_ioserirq_handler,
+				IRQF_TRIGGER_HIGH,
+				"TPM SERIRQ management", chip);
+		if (err < 0) {
+			dev_err(chip->dev , "TPM SERIRQ signals %d not available\n",
+			gpio_to_irq(platform_data->io_serirq));
+			goto _irq_set;
+		}
+
+		err = I2C_READ_DATA(client, TPM_INT_ENABLE, &intmask, 1);
+		if (err < 0)
+			goto _irq_set;
+
+		intmask |= TPM_INTF_CMD_READY_INT
+			|  TPM_INTF_FIFO_AVALAIBLE_INT
+			|  TPM_INTF_WAKE_UP_READY_INT
+			|  TPM_INTF_LOCALITY_CHANGE_INT
+			|  TPM_INTF_STS_VALID_INT
+			|  TPM_INTF_DATA_AVAIL_INT;
+
+		err = I2C_WRITE_DATA(client, TPM_INT_ENABLE, &intmask, 1);
+		if (err < 0)
+			goto _irq_set;
+
+		intmask = TPM_GLOBAL_INT_ENABLE;
+		err = I2C_WRITE_DATA(client, TPM_INT_ENABLE + 3, &intmask, 1);
+		if (err < 0)
+			goto _irq_set;
+
+		err = I2C_READ_DATA(client, TPM_INT_STATUS, &intmask, 1);
+		if (err < 0)
+			goto _irq_set;
+
+		chip->vendor.irq = interrupts;
+
+		tpm_gen_interrupt(chip);
+	}
+
+	tpm_get_timeouts(chip);
+
+	i2c_set_clientdata(client, chip);
+	platform_data->bChipF = false;
+
+	dev_info(chip->dev, "TPM I2C Initialized\n");
+	return 0;
+_irq_set:
+	free_irq(gpio_to_irq(platform_data->io_serirq), (void *) chip);
+_gpio_init2:
+	if (platform_data && interrupts)
+		gpio_free(platform_data->io_serirq);
+_gpio_init1:
+	if (platform_data && power_mgt)
+		gpio_free(platform_data->io_lpcpd);
+_tpm_clean_response:
+	tpm_remove_hardware(chip->dev);
+	if (platform_data->tpm_i2c_buffer[1] != NULL) {
+		kzfree(platform_data->tpm_i2c_buffer[1]);
+		platform_data->tpm_i2c_buffer[1] = NULL;
+	}
+_tpm_clean_answer:
+	if (platform_data->tpm_i2c_buffer[0] != NULL) {
+		kzfree(platform_data->tpm_i2c_buffer[0]);
+		platform_data->tpm_i2c_buffer[0] = NULL;
+	}
+
+	platform_data->bChipF = true;
+end:
+	pr_info("TPM I2C initialisation fail\n");
+	return err;
+}
+
+/*
+ * tpm_st33_i2c_remove remove the TPM device
+ * @param: client, the i2c_client drescription (TPM I2C description).
+		clear_bit(0, &chip->is_open);
+ * @return: 0 in case of success.
+ */
+static __devexit int tpm_st33_i2c_remove(struct i2c_client *client)
+{
+	struct tpm_chip *chip = (struct tpm_chip *)i2c_get_clientdata(client);
+	struct st33zp24_platform_data *pin_infos =
+		((struct i2c_client *) chip->vendor.iobase)->dev.platform_data;
+
+	if (pin_infos != NULL) {
+		free_irq(pin_infos->io_serirq, chip);
+
+		gpio_free(pin_infos->io_serirq);
+		gpio_free(pin_infos->io_lpcpd);
+
+		if (pin_infos->bChipF != true)
+			tpm_remove_hardware(chip->dev);
+		if (pin_infos->tpm_i2c_buffer[1] != NULL) {
+			kzfree(pin_infos->tpm_i2c_buffer[1]);
+			pin_infos->tpm_i2c_buffer[1] = NULL;
+		}
+		if (pin_infos->tpm_i2c_buffer[0] != NULL) {
+			kzfree(pin_infos->tpm_i2c_buffer[0]);
+			pin_infos->tpm_i2c_buffer[0] = NULL;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * tpm_st33_i2c_pm_suspend suspend the TPM device
+ * Added: Work around when suspend and no tpm application is running, suspend
+ * may fail because chip->data_buffer is not set (only set in tpm_open in Linux
+ * TPM core)
+ * @param: client, the i2c_client drescription (TPM I2C description).
+ * @param: mesg, the power management message.
+ * @return: 0 in case of success.
+ */
+static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	struct tpm_chip *chip =
+	    (struct tpm_chip *)i2c_get_clientdata(client);
+	struct st33zp24_platform_data *pin_infos =
+		((struct i2c_client *)chip->vendor.iobase)->dev.platform_data;
+	int ret = 0;
+
+	if (power_mgt)
+		gpio_set_value(pin_infos->io_lpcpd, 0);
+	else{
+		if (chip->data_buffer == NULL)
+			chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
+		ret = tpm_pm_suspend(&client->dev, mesg);
+	}
+	return ret;
+}				/* tpm_st33_i2c_suspend() */
+
+/*
+ * tpm_st33_i2c_pm_resume resume the TPM device
+ * @param: client, the i2c_client drescription (TPM I2C description).
+ * @return: 0 in case of success.
+ */
+static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
+{
+	struct tpm_chip *chip =
+	    (struct tpm_chip *)i2c_get_clientdata(client);
+	struct st33zp24_platform_data *pin_infos =
+		((struct i2c_client *)chip->vendor.iobase)->dev.platform_data;
+
+	int ret = 0;
+
+	if (power_mgt) {
+		gpio_set_value(pin_infos->io_lpcpd, 1);
+		ret = wait_for_serirq_timeout(chip,
+					  (chip->vendor.status(chip) &&
+					  TPM_STS_VALID) == TPM_STS_VALID,
+					  chip->vendor.timeout_b);
+	} else{
+	if (chip->data_buffer == NULL)
+		chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
+	ret = tpm_pm_resume(&client->dev);
+	if (!ret)
+		tpm_continue_selftest_nocheck(chip);
+	}
+	return ret;
+}				/* tpm_st33_i2c_pm_resume() */
+
+static const struct i2c_device_id tpm_st33_i2c_id[] = {
+	{TPM_ST33_I2C, 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, tpm_st33_i2c_id);
+
+static struct i2c_driver tpm_st33_i2c_driver = {
+	.driver = {
+		   .owner = THIS_MODULE,
+		   .name = TPM_ST33_I2C,
+		   },
+	.probe = tpm_st33_i2c_probe,
+	.remove = tpm_st33_i2c_remove,
+	.resume = tpm_st33_i2c_pm_resume,
+	.suspend = tpm_st33_i2c_pm_suspend,
+	.id_table = tpm_st33_i2c_id
+};
+
+/*
+ * tpm_st33_i2c_init initialize driver
+ * @return: 0 if successful, else non zero value.
+ */
+static int __init tpm_st33_i2c_init(void)
+{
+	return i2c_add_driver(&tpm_st33_i2c_driver);
+}
+
+/*
+ * tpm_st33_i2c_exit The kernel calls this function during unloading the
+ * module or during shut down process
+ */
+static void __exit tpm_st33_i2c_exit(void)
+{
+	i2c_del_driver(&tpm_st33_i2c_driver);
+}
+
+module_init(tpm_st33_i2c_init);
+module_exit(tpm_st33_i2c_exit);
+
+MODULE_AUTHOR("Christophe Ricard (tpmsupport@st.com)");
+MODULE_DESCRIPTION("STM TPM I2C ST33 Driver");
+MODULE_VERSION("1.2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_stm_st33_i2c.h b/drivers/char/tpm/tpm_stm_st33_i2c.h
new file mode 100644
index 0000000..d390542
--- /dev/null
+++ b/drivers/char/tpm/tpm_stm_st33_i2c.h
@@ -0,0 +1,81 @@
+/*
+ * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
+ * Copyright (C) 2009, 2010  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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * STMicroelectronics version 1.2.0, Copyright (C) 2010
+ * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
+ * This is free software, and you are welcome to redistribute it
+ * under certain conditions.
+ *
+ * @Author: Christophe RICARD tpmsupport@st.com
+ *
+ * @File: stm_st33_tpm_i2c.h
+ *
+ * @Date: 09/15/2010
+ */
+#ifndef __STM_ST33_TPM_I2C_MAIN_H__
+#define __STM_ST33_TPM_I2C_MAIN_H__
+
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/sysfs.h>
+#include <linux/gpio.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+#include "tpm.h"
+
+#define MINOR_NUM_I2C		224
+
+#define TPM_ACCESS			(0x0)
+#define TPM_STS				(0x18)
+#define TPM_HASH_END			(0x20)
+#define TPM_DATA_FIFO			(0x24)
+#define TPM_HASH_DATA			(0x24)
+#define TPM_HASH_START			(0x28)
+#define TPM_INTF_CAPABILITY		(0x14)
+#define TPM_INT_STATUS			(0x10)
+#define TPM_INT_ENABLE			(0x08)
+
+#define TPM_DUMMY_BYTE			0xAA
+#define TPM_WRITE_DIRECTION		0x80
+#define TPM_HEADER_SIZE			10
+#define TPM_BUFSIZE			2048
+
+#define LOCALITY0		0
+
+struct st_tpm_hash {
+	int size;
+	u8 *data;
+};
+
+#endif /* __STM_ST33_TPM_I2C_MAIN_H__ */
diff --git a/include/linux/i2c/tpm_stm_st33_i2c.h b/include/linux/i2c/tpm_stm_st33_i2c.h
new file mode 100644
index 0000000..e3ce42d
--- /dev/null
+++ b/include/linux/i2c/tpm_stm_st33_i2c.h
@@ -0,0 +1,47 @@
+/*
+* STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
+* Copyright (C) 2009, 2010 STMicroelectronics
+* Christophe RICARD tpmsupport@st.com
+* 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, write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* STMicroelectronics version 1.2.0, Copyright (C) 2010
+* STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
+* This is free software, and you are welcome to redistribute it
+* under certain conditions.
+*
+* @File: stm_st33_tpm_i2c.h
+*
+* @Date: 06/15/2008
+*/
+#ifndef __STM_ST33_TPM_I2C_H__
+#define __STM_ST33_TPM_I2C_H__
+
+#include <linux/i2c.h>
+
+#define TPM_ST33_I2C			"st33zp24_i2c"
+#define TPM_I2C_ST33_ADDR_WR_LOC0	(0x26 >> 1)
+
+
+struct st33zp24_platform_data {
+	int io_serirq;
+	int io_lpcpd;
+	struct i2c_client *client;
+	bool bChipF;
+	u8 *tpm_i2c_buffer[2]; /* 0 Request 1 Response */
+	struct completion irq_detection;
+	struct mutex lock;
+};
+
+#endif /* __STM_ST33_TPM_I2C_H__ */
-- 
1.7.9.5


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

* [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 2.6
  2012-11-19 22:15 [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x Mathias Leblanc
@ 2012-11-19 22:15 ` Mathias Leblanc
  2012-11-26 17:46 ` [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x Kent Yoder
  1 sibling, 0 replies; 33+ messages in thread
From: Mathias Leblanc @ 2012-11-19 22:15 UTC (permalink / raw)
  To: Kent Yoder, Rajiv Andrade, Marcel Selhorst, Sirrix AG,
	tpmdd-devel, Debora Velarde
  Cc: linux-kernel, Jean-Luc Blanc, Mathias Leblanc

 * STMicroelectronics version 1.2.0, Copyright (C) 2010
 * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
 * This is free software, and you are welcome to redistribute it
 * under certain conditions.

This is the driver for TPM chip from ST Microelectronics.

If you have a TPM security chip from STMicroelectronics working with
an I2C, in menuconfig or .config choose the tpm driver on
device --> tpm and activate the protocol of your choice before compiling
the kernel.
The driver will be accessible from within Linux.

Tested on linux x86/x64, beagleboard REV B & XM REV C and CHROMIUM OS
on kernel 2.6

Signed-off-by: Mathias Leblanc <mathias.leblanc@st.com>
---
 drivers/char/tpm/tpm_stm_st33_i2c.c  |  904 ++++++++++++++++++++++++++++++++++
 drivers/char/tpm/tpm_stm_st33_i2c.h  |   81 +++
 include/linux/i2c/tpm_stm_st33_i2c.h |   47 ++
 3 files changed, 1032 insertions(+)
 create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.c
 create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.h
 create mode 100644 include/linux/i2c/tpm_stm_st33_i2c.h

diff --git a/drivers/char/tpm/tpm_stm_st33_i2c.c b/drivers/char/tpm/tpm_stm_st33_i2c.c
new file mode 100644
index 0000000..bf18885
--- /dev/null
+++ b/drivers/char/tpm/tpm_stm_st33_i2c.c
@@ -0,0 +1,904 @@
+/*
+ * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
+ * Copyright (C) 2009, 2010  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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * STMicroelectronics version 1.2.0, Copyright (C) 2010
+ * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
+ * This is free software, and you are welcome to redistribute it
+ * under certain conditions.
+ *
+ * @Author: Christophe RICARD tpmsupport@st.com
+ *
+ * @File: tpm_stm_st33_i2c.c
+ *
+ * @Synopsis:
+ *	09/15/2010:	First shot driver tpm_tis driver for
+			 lpc is used as model.
+ */
+
+#include <linux/i2c/tpm_stm_st33_i2c.h>
+
+#include "tpm_stm_st33_i2c.h"
+
+enum stm33zp24_access {
+	TPM_ACCESS_VALID = 0x80,
+	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
+	TPM_ACCESS_REQUEST_PENDING = 0x04,
+	TPM_ACCESS_REQUEST_USE = 0x02,
+};
+
+enum stm33zp24_status {
+	TPM_STS_VALID = 0x80,
+	TPM_STS_COMMAND_READY = 0x40,
+	TPM_STS_GO = 0x20,
+	TPM_STS_DATA_AVAIL = 0x10,
+	TPM_STS_DATA_EXPECT = 0x08,
+};
+
+enum stm33zp24_int_flags {
+	TPM_GLOBAL_INT_ENABLE = 0x80,
+	TPM_INTF_CMD_READY_INT = 0x080,
+	TPM_INTF_FIFO_AVALAIBLE_INT = 0x040,
+	TPM_INTF_WAKE_UP_READY_INT = 0x020,
+	TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
+	TPM_INTF_STS_VALID_INT = 0x002,
+	TPM_INTF_DATA_AVAIL_INT = 0x001,
+};
+
+enum tis_defaults {
+	TIS_SHORT_TIMEOUT = 750,
+	TIS_LONG_TIMEOUT = 2000,
+};
+
+/*
+ * write8_reg
+ * Send byte to the TIS register according to the ST33ZP24 I2C protocol.
+ * @param: tpm_register, the tpm tis register where the data should be written
+ * @param: tpm_data, the tpm_data to write inside the tpm_register
+ * @param: tpm_size, The length of the data
+ * @return: Returns negative errno, or else the number of bytes written.
+ */
+static int write8_reg(struct i2c_client *client, u8 tpm_register,
+		      u8 *tpm_data, u16 tpm_size)
+{
+	u8 data;
+	int value = 0;
+	struct st33zp24_platform_data *pin_infos;
+
+	pin_infos = client->dev.platform_data;
+
+	data = tpm_register;
+	memcpy(pin_infos->tpm_i2c_buffer[0], &data, sizeof(data));
+	memcpy(pin_infos->tpm_i2c_buffer[0] + 1, tpm_data, tpm_size);
+	value = i2c_master_send(client, pin_infos->tpm_i2c_buffer[0],
+				tpm_size + 1);
+	return value;
+} /* write8_reg() */
+
+/*
+ * read8_reg
+ * Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
+ * @param: tpm_register, the tpm tis register where the data should be read
+ * @param: tpm_data, the TPM response
+ * @param: tpm_size, tpm TPM response size to read.
+ * @return: number of byte read successfully: should be one if success.
+ */
+static int read8_reg(struct i2c_client *client, u8 tpm_register,
+		    u8 *tpm_data, int tpm_size)
+{
+	u8 status = 0;
+	u8 data;
+	struct st33zp24_platform_data *pin_infos;
+
+	pin_infos = client->dev.platform_data;
+
+	data = TPM_DUMMY_BYTE;
+	status = write8_reg(client, tpm_register, &data, 1);
+	if (status == 2)
+		status = i2c_master_recv(client, tpm_data, tpm_size);
+	return status;
+} /* read8_reg() */
+
+/*
+ * I2C_WRITE_DATA
+ * Send byte to the TIS register according to the ST33ZP24 I2C protocol.
+ * @param: client, the chip description
+ * @param: tpm_register, the tpm tis register where the data should be written
+ * @param: tpm_data, the tpm_data to write inside the tpm_register
+ * @param: tpm_size, The length of the data
+ * @return: number of byte written successfully: should be one if success.
+ */
+#define I2C_WRITE_DATA(client, tpm_register, tpm_data, tpm_size) \
+	(write8_reg(client, tpm_register | \
+	TPM_WRITE_DIRECTION, tpm_data, tpm_size))
+
+/*
+ * I2C_READ_DATA
+ * Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
+ * @param: tpm, the chip description
+ * @param: tpm_register, the tpm tis register where the data should be read
+ * @param: tpm_data, the TPM response
+ * @param: tpm_size, tpm TPM response size to read.
+ * @return: number of byte read successfully: should be one if success.
+ */
+#define I2C_READ_DATA(client, tpm_register, tpm_data, tpm_size) \
+	(read8_reg(client, tpm_register, tpm_data, tpm_size))
+
+/*
+ * clear_interruption
+ * clear the TPM interrupt register.
+ * @param: tpm, the chip description
+ */
+static void clear_interruption(struct i2c_client *client)
+{
+	u8 interrupt;
+	I2C_READ_DATA(client, TPM_INT_STATUS, &interrupt, 1);
+	I2C_WRITE_DATA(client, TPM_INT_STATUS, &interrupt, 1);
+	I2C_READ_DATA(client, TPM_INT_STATUS, &interrupt, 1);
+} /* clear_interruption() */
+
+/*
+ * _wait_for_interrupt_serirq_timeout
+ * @param: tpm, the chip description
+ * @param: timeout, the timeout of the interrupt
+ * @return: the status of the interruption.
+ */
+static long _wait_for_interrupt_serirq_timeout(struct tpm_chip *chip,
+						unsigned long timeout)
+{
+	long status;
+	struct i2c_client *client;
+	struct st33zp24_platform_data *pin_infos;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+	pin_infos = client->dev.platform_data;
+
+	status = wait_for_completion_interruptible_timeout(
+					&pin_infos->irq_detection,
+						timeout);
+	if (status > 0)
+		enable_irq(gpio_to_irq(pin_infos->io_serirq));
+	gpio_direction_input(pin_infos->io_serirq);
+
+	return status;
+} /* wait_for_interrupt_serirq_timeout() */
+
+int wait_for_serirq_timeout(struct tpm_chip *chip, bool condition,
+				 unsigned long timeout)
+{
+	int status = 2;
+	struct i2c_client *client;
+	struct st33zp24_platform_data *pin_infos;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+	pin_infos = client->dev.platform_data;
+
+	status = _wait_for_interrupt_serirq_timeout(chip, timeout);
+	if (!status) {
+		status = -EBUSY;
+	} else{
+		clear_interruption(client);
+		if (condition)
+			status = 1;
+	}
+	return status;
+}
+
+/*
+ * tpm_stm_i2c_cancel, cancel is not implemented.
+ * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h
+ */
+static void tpm_stm_i2c_cancel(struct tpm_chip *chip)
+{
+	struct i2c_client *client;
+	u8 data;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+
+	data = TPM_STS_COMMAND_READY;
+	I2C_WRITE_DATA(client, TPM_STS, &data, 1);
+	if (chip->vendor.irq)
+		wait_for_serirq_timeout(chip, 1, chip->vendor.timeout_a);
+}	/* tpm_stm_i2c_cancel() */
+
+/*
+ * tpm_stm_spi_status return the TPM_STS register
+ * @param: chip, the tpm chip description
+ * @return: the TPM_STS register value.
+ */
+static u8 tpm_stm_i2c_status(struct tpm_chip *chip)
+{
+	struct i2c_client *client;
+	u8 data;
+	client = (struct i2c_client *) chip->vendor.iobase;
+
+	I2C_READ_DATA(client, TPM_STS, &data, 1);
+	return data;
+}				/* tpm_stm_i2c_status() */
+
+
+/*
+ * check_locality if the locality is active
+ * @param: chip, the tpm chip description
+ * @return: the active locality or -EACCESS.
+ */
+static int check_locality(struct tpm_chip *chip)
+{
+	struct i2c_client *client;
+	u8 data;
+	u8 status;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+
+	status = I2C_READ_DATA(client, TPM_ACCESS, &data, 1);
+	if (status && (data &
+		(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
+		(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
+		return chip->vendor.locality;
+
+	return -EACCES;
+
+} /* check_locality() */
+
+/*
+ * request_locality request the TPM locality
+ * @param: chip, the chip description
+ * @return: the active locality or EACCESS.
+ */
+static int request_locality(struct tpm_chip *chip)
+{
+	unsigned long stop;
+	long rc;
+	struct i2c_client *client;
+	u8 data;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+
+	if (check_locality(chip) == chip->vendor.locality)
+		return chip->vendor.locality;
+
+	data = TPM_ACCESS_REQUEST_USE;
+	rc = I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1);
+	if (rc < 0)
+		goto end;
+
+	if (chip->vendor.irq) {
+		rc = wait_for_serirq_timeout(chip, (check_locality
+						       (chip) >= 0),
+						      chip->vendor.timeout_a);
+		if (rc > 0)
+			return chip->vendor.locality;
+	} else{
+		stop = jiffies + chip->vendor.timeout_a;
+		do {
+			if (check_locality(chip) >= 0)
+				return chip->vendor.locality;
+			msleep(TPM_TIMEOUT);
+		} while (time_before(jiffies, stop));
+	}
+	rc = -EACCES;
+end:
+	return rc;
+} /* request_locality() */
+
+/*
+ * release_locality release the active locality
+ * @param: chip, the tpm chip description.
+ */
+static void release_locality(struct tpm_chip *chip)
+{
+	struct i2c_client *client;
+	u8 data;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+	data = TPM_ACCESS_ACTIVE_LOCALITY;
+
+	I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1);
+}
+
+/*
+ * get_burstcount return the burstcount address 0x19 0x1A
+ * @param: chip, the chip description
+ * return: the burstcount.
+ */
+static int get_burstcount(struct tpm_chip *chip)
+{
+	unsigned long stop;
+	int burstcnt, status;
+	u8 tpm_reg, temp;
+
+	struct i2c_client *client = (struct i2c_client *) chip->vendor.iobase;
+
+	stop = jiffies + chip->vendor.timeout_d;
+	do {
+		tpm_reg = TPM_STS + 1;
+		status = I2C_READ_DATA(client, tpm_reg, &temp, 1);
+		if (status < 0)
+			goto end;
+
+		tpm_reg = tpm_reg + 1;
+		burstcnt = temp;
+		status = I2C_READ_DATA(client, tpm_reg, &temp, 1);
+		if (status < 0)
+			goto end;
+
+		burstcnt |= temp << 8;
+		if (burstcnt)
+			return burstcnt;
+		msleep(TPM_TIMEOUT);
+	} while (time_before(jiffies, stop));
+
+end:
+	return -EBUSY;
+} /* get_burstcount() */
+
+/*
+ * wait_for_stat wait for a TPM_STS value
+ * @param: chip, the tpm chip description
+ * @param: mask, the value mask to wait
+ * @param: timeout, the timeout
+ * @param: queue, the wait queue.
+ * @return: the tpm status, 0 if success, -ETIME if timeout is reached.
+ */
+static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
+			 wait_queue_head_t *queue)
+{
+	unsigned long stop;
+	long rc;
+	u8 status;
+
+	 if (chip->vendor.irq) {
+		rc = wait_for_serirq_timeout(chip, ((tpm_stm_i2c_status
+							(chip) & mask) ==
+						       mask), timeout);
+		if (rc > 0)
+			return 0;
+	} else{
+		stop = jiffies + timeout;
+		do {
+			msleep(TPM_TIMEOUT);
+			status = tpm_stm_i2c_status(chip);
+			if ((status & mask) == mask)
+				return 0;
+		} while (time_before(jiffies, stop));
+	}
+	return -ETIME;
+} /* wait_for_stat() */
+
+/*
+ * recv_data receive data
+ * @param: chip, the tpm chip description
+ * @param: buf, the buffer where the data are received
+ * @param: count, the number of data to receive
+ * @return: the number of bytes read from TPM FIFO.
+ */
+static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	int size = 0, burstcnt, len;
+	struct i2c_client *client;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+
+	while (size < count &&
+	       wait_for_stat(chip,
+			     TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+			     chip->vendor.timeout_c,
+			     &chip->vendor.read_queue)
+	       == 0) {
+		burstcnt = get_burstcount(chip);
+		len = min_t(int, burstcnt, count - size);
+		I2C_READ_DATA(client, TPM_DATA_FIFO, buf + size, len);
+		size += len;
+	}
+	return size;
+}
+
+/*
+ * tpm_ioserirq_handler the serirq irq handler
+ * @param: irq, the tpm chip description
+ * @param: dev_id, the description of the chip
+ * @return: the status of the handler.
+ */
+static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id)
+{
+	struct tpm_chip *chip = dev_id;
+	struct i2c_client *client;
+	struct st33zp24_platform_data *pin_infos;
+
+	disable_irq_nosync(irq);
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+	pin_infos = client->dev.platform_data;
+
+	complete(&pin_infos->irq_detection);
+	return IRQ_HANDLED;
+} /* tpm_ioserirq_handler() */
+
+
+/*
+ * tpm_stm_i2c_send send TPM commands through the I2C bus.
+ *
+ * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h
+ * @param: buf,	the buffer to send.
+ * @param: count, the number of bytes to send.
+ * @return: In case of success the number of bytes sent.
+ *			In other case, a < 0 value describing the issue.
+ */
+static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
+			    size_t len)
+{
+	u32 ret = 0, ordinal,
+	    status,
+	    burstcnt = 0, i, size;
+	u8 data;
+	struct i2c_client *client;
+	struct st33zp24_platform_data *pin_infos;
+
+	if (chip == NULL)
+		return -EBUSY;
+	if (len < TPM_HEADER_SIZE)
+		return -EBUSY;
+
+	client = (struct i2c_client *)chip->vendor.iobase;
+	pin_infos = client->dev.platform_data;
+
+	ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
+
+	client->flags = 0;
+
+	ret = request_locality(chip);
+	if (ret < 0)
+		return ret;
+
+	status = tpm_stm_i2c_status(chip);
+	if ((status & TPM_STS_COMMAND_READY) == 0) {
+		tpm_stm_i2c_cancel(chip);
+		if (wait_for_stat
+		    (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
+		     &chip->vendor.int_queue) < 0) {
+			ret = -ETIME;
+			goto out_err;
+		}
+	}
+
+	for (i = 0 ; i < len - 1 ;) {
+		burstcnt = get_burstcount(chip);
+		size = min_t(int, len - i - 1, burstcnt);
+		ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf, size);
+		if (ret < 0)
+			goto out_err;
+
+		i += size;
+	}
+
+	status = tpm_stm_i2c_status(chip);
+	if ((status & TPM_STS_DATA_EXPECT) == 0) {
+		ret = -EIO;
+		goto out_err;
+	}
+
+	ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf + len - 1, 1);
+	if (ret < 0)
+		goto out_err;
+
+	status = tpm_stm_i2c_status(chip);
+	if ((status & TPM_STS_DATA_EXPECT) != 0) {
+		ret = -EIO;
+		goto out_err;
+	}
+
+	data = TPM_STS_GO;
+	I2C_WRITE_DATA(client, TPM_STS, &data, 1);
+
+	return len;
+out_err:
+	tpm_stm_i2c_cancel(chip);
+	release_locality(chip);
+	return ret;
+}
+
+/*
+ * tpm_stm_i2c_recv received TPM response through the I2C bus.
+ * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h.
+ * @param: buf,	the buffer to store datas.
+ * @param: count, the number of bytes to send.
+ * @return: In case of success the number of bytes received.
+ *		In other case, a < 0 value describing the issue.
+ */
+static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
+			    size_t count)
+{
+	int size = 0;
+	int expected;
+
+	struct i2c_client *client;
+	struct st33zp24_platform_data *pin_infos;
+
+	client = (struct i2c_client *)chip->vendor.iobase;
+	pin_infos = client->dev.platform_data;
+
+
+	if (chip == NULL)
+		return -EBUSY;
+
+	if (count < TPM_HEADER_SIZE) {
+		size = -EIO;
+		goto out;
+	}
+
+	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;
+	}
+
+out:
+	chip->vendor.cancel(chip);
+	release_locality(chip);
+	return size;
+}
+
+static const struct file_operations tpm_st33_i2c_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.read = tpm_read,
+	.write = tpm_write,
+	.open = tpm_open,
+	.release = tpm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute *stm_tpm_attrs[] = {
+	&dev_attr_pubek.attr,
+	&dev_attr_pcrs.attr,
+	&dev_attr_enabled.attr,
+	&dev_attr_active.attr,
+	&dev_attr_owned.attr,
+	&dev_attr_temp_deactivated.attr,
+	&dev_attr_caps.attr,
+	&dev_attr_cancel.attr, NULL,
+};
+
+static struct attribute_group stm_tpm_attr_grp = {
+	.attrs = stm_tpm_attrs
+};
+
+static struct tpm_vendor_specific st_i2c_tpm = {
+	.send = tpm_stm_i2c_send,
+	.recv = tpm_stm_i2c_recv,
+	.cancel = tpm_stm_i2c_cancel,
+	.status = tpm_stm_i2c_status,
+	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_canceled = TPM_STS_COMMAND_READY,
+	.attr_group = &stm_tpm_attr_grp,
+	.miscdev = {.fops = &tpm_st33_i2c_fops,},
+};
+
+static int interrupts ;
+module_param(interrupts, int, 0444);
+MODULE_PARM_DESC(interrupts, "Enable interrupts");
+
+static int power_mgt = 1;
+module_param(power_mgt, int, 0444);
+MODULE_PARM_DESC(power_mgt, "Power Management");
+
+/*
+ * tpm_st33_i2c_probe initialize the TPM device
+ * @param: client, the i2c_client drescription (TPM I2C description).
+ * @param: id, the i2c_device_id struct.
+ * @return: 0 in case of success.
+ *	 -1 in other case.
+ */
+static int
+tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	u32 err;
+	u8 intmask;
+	struct tpm_chip *chip;
+	struct st33zp24_platform_data *platform_data;
+
+	err = 0;
+
+	if (client == NULL) {
+		dev_info(&client->dev, "client is NULL. exiting.\n");
+		err = -ENODEV;
+		goto end;
+	}
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_info(&client->dev, "client not i2c capable\n");
+		err = -ENODEV;
+		goto end;
+	}
+
+	chip = tpm_register_hardware(&client->dev, &st_i2c_tpm);
+	if (!chip) {
+		dev_info(&client->dev, "fail chip\n");
+		err = -ENODEV;
+		goto end;
+	}
+
+	platform_data = client->dev.platform_data;
+	platform_data->tpm_i2c_buffer[0] =
+	    kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+	if (platform_data->tpm_i2c_buffer[0] == NULL) {
+		err = -ENOMEM;
+		goto _tpm_clean_answer;
+	}
+	platform_data->tpm_i2c_buffer[1] =
+	    kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+	if (platform_data->tpm_i2c_buffer[1] == NULL) {
+		err = -ENOMEM;
+		goto _tpm_clean_response;
+	}
+
+	chip->vendor.iobase = client;
+
+	chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
+	chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+
+	chip->vendor.locality = LOCALITY0;
+
+	if (power_mgt) {
+		err = gpio_request(platform_data->io_lpcpd, "TPM IO_LPCPD");
+		if (err)
+			goto _gpio_init1;
+		gpio_set_value(platform_data->io_lpcpd, 1);
+	}
+
+	if (interrupts) {
+		init_completion(&platform_data->irq_detection);
+		if (request_locality(chip) != LOCALITY0) {
+			err = -ENODEV;
+			goto _tpm_clean_response;
+		}
+		err = gpio_request(platform_data->io_serirq, "TPM IO_SERIRQ");
+		if (err)
+			goto _gpio_init2;
+
+		clear_interruption(client);
+		err = request_irq(gpio_to_irq(platform_data->io_serirq),
+				&tpm_ioserirq_handler,
+				IRQF_TRIGGER_HIGH,
+				"TPM SERIRQ management", chip);
+		if (err < 0) {
+			dev_err(chip->dev , "TPM SERIRQ signals %d not available\n",
+			gpio_to_irq(platform_data->io_serirq));
+			goto _irq_set;
+		}
+
+		err = I2C_READ_DATA(client, TPM_INT_ENABLE, &intmask, 1);
+		if (err < 0)
+			goto _irq_set;
+
+		intmask |= TPM_INTF_CMD_READY_INT
+			|  TPM_INTF_FIFO_AVALAIBLE_INT
+			|  TPM_INTF_WAKE_UP_READY_INT
+			|  TPM_INTF_LOCALITY_CHANGE_INT
+			|  TPM_INTF_STS_VALID_INT
+			|  TPM_INTF_DATA_AVAIL_INT;
+
+		err = I2C_WRITE_DATA(client, TPM_INT_ENABLE, &intmask, 1);
+		if (err < 0)
+			goto _irq_set;
+
+		intmask = TPM_GLOBAL_INT_ENABLE;
+		err = I2C_WRITE_DATA(client, TPM_INT_ENABLE + 3, &intmask, 1);
+		if (err < 0)
+			goto _irq_set;
+
+		err = I2C_READ_DATA(client, TPM_INT_STATUS, &intmask, 1);
+		if (err < 0)
+			goto _irq_set;
+
+		chip->vendor.irq = interrupts;
+
+		tpm_gen_interrupt(chip);
+	}
+
+	tpm_get_timeouts(chip);
+
+	i2c_set_clientdata(client, chip);
+	platform_data->bChipF = false;
+
+	dev_info(chip->dev, "TPM I2C Initialized\n");
+	return 0;
+_irq_set:
+	free_irq(gpio_to_irq(platform_data->io_serirq), (void *) chip);
+_gpio_init2:
+	if (platform_data && interrupts)
+		gpio_free(platform_data->io_serirq);
+_gpio_init1:
+	if (platform_data && power_mgt)
+		gpio_free(platform_data->io_lpcpd);
+_tpm_clean_response:
+	tpm_remove_hardware(chip->dev);
+	if (platform_data->tpm_i2c_buffer[1] != NULL) {
+		kzfree(platform_data->tpm_i2c_buffer[1]);
+		platform_data->tpm_i2c_buffer[1] = NULL;
+	}
+_tpm_clean_answer:
+	if (platform_data->tpm_i2c_buffer[0] != NULL) {
+		kzfree(platform_data->tpm_i2c_buffer[0]);
+		platform_data->tpm_i2c_buffer[0] = NULL;
+	}
+
+	platform_data->bChipF = true;
+end:
+	pr_info("TPM I2C initialisation fail\n");
+	return err;
+}
+
+/*
+ * tpm_st33_i2c_remove remove the TPM device
+ * @param: client, the i2c_client drescription (TPM I2C description).
+		clear_bit(0, &chip->is_open);
+ * @return: 0 in case of success.
+ */
+static __devexit int tpm_st33_i2c_remove(struct i2c_client *client)
+{
+	struct tpm_chip *chip = (struct tpm_chip *)i2c_get_clientdata(client);
+	struct st33zp24_platform_data *pin_infos =
+		((struct i2c_client *) chip->vendor.iobase)->dev.platform_data;
+
+	if (pin_infos != NULL) {
+		free_irq(pin_infos->io_serirq, chip);
+
+		gpio_free(pin_infos->io_serirq);
+		gpio_free(pin_infos->io_lpcpd);
+
+		if (pin_infos->bChipF != true)
+			tpm_remove_hardware(chip->dev);
+		if (pin_infos->tpm_i2c_buffer[1] != NULL) {
+			kzfree(pin_infos->tpm_i2c_buffer[1]);
+			pin_infos->tpm_i2c_buffer[1] = NULL;
+		}
+		if (pin_infos->tpm_i2c_buffer[0] != NULL) {
+			kzfree(pin_infos->tpm_i2c_buffer[0]);
+			pin_infos->tpm_i2c_buffer[0] = NULL;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * tpm_st33_i2c_pm_suspend suspend the TPM device
+ * Added: Work around when suspend and no tpm application is running, suspend
+ * may fail because chip->data_buffer is not set (only set in tpm_open in Linux
+ * TPM core)
+ * @param: client, the i2c_client drescription (TPM I2C description).
+ * @param: mesg, the power management message.
+ * @return: 0 in case of success.
+ */
+static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	struct tpm_chip *chip =
+	    (struct tpm_chip *)i2c_get_clientdata(client);
+	struct st33zp24_platform_data *pin_infos =
+		((struct i2c_client *)chip->vendor.iobase)->dev.platform_data;
+	int ret = 0;
+
+	if (power_mgt)
+		gpio_set_value(pin_infos->io_lpcpd, 0);
+	else{
+		if (chip->data_buffer == NULL)
+			chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
+		ret = tpm_pm_suspend(&client->dev, mesg);
+	}
+	return ret;
+}				/* tpm_st33_i2c_suspend() */
+
+/*
+ * tpm_st33_i2c_pm_resume resume the TPM device
+ * @param: client, the i2c_client drescription (TPM I2C description).
+ * @return: 0 in case of success.
+ */
+static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
+{
+	struct tpm_chip *chip =
+	    (struct tpm_chip *)i2c_get_clientdata(client);
+	struct st33zp24_platform_data *pin_infos =
+		((struct i2c_client *)chip->vendor.iobase)->dev.platform_data;
+
+	int ret = 0;
+
+	if (power_mgt) {
+		gpio_set_value(pin_infos->io_lpcpd, 1);
+		ret = wait_for_serirq_timeout(chip,
+					  (chip->vendor.status(chip) &&
+					  TPM_STS_VALID) == TPM_STS_VALID,
+					  chip->vendor.timeout_b);
+	} else{
+	if (chip->data_buffer == NULL)
+		chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
+	ret = tpm_pm_resume(&client->dev);
+	if (!ret)
+		tpm_continue_selftest(chip);
+	}
+	return ret;
+}				/* tpm_st33_i2c_pm_resume() */
+
+static const struct i2c_device_id tpm_st33_i2c_id[] = {
+	{TPM_ST33_I2C, 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, tpm_st33_i2c_id);
+
+static struct i2c_driver tpm_st33_i2c_driver = {
+	.driver = {
+		   .owner = THIS_MODULE,
+		   .name = TPM_ST33_I2C,
+		   },
+	.probe = tpm_st33_i2c_probe,
+	.remove = tpm_st33_i2c_remove,
+	.resume = tpm_st33_i2c_pm_resume,
+	.suspend = tpm_st33_i2c_pm_suspend,
+	.id_table = tpm_st33_i2c_id
+};
+
+/*
+ * tpm_st33_i2c_init initialize driver
+ * @return: 0 if successful, else non zero value.
+ */
+static int __init tpm_st33_i2c_init(void)
+{
+	return i2c_add_driver(&tpm_st33_i2c_driver);
+}
+
+/*
+ * tpm_st33_i2c_exit The kernel calls this function during unloading the
+ * module or during shut down process
+ */
+static void __exit tpm_st33_i2c_exit(void)
+{
+	i2c_del_driver(&tpm_st33_i2c_driver);
+}
+
+module_init(tpm_st33_i2c_init);
+module_exit(tpm_st33_i2c_exit);
+
+MODULE_AUTHOR("Christophe Ricard (tpmsupport@st.com)");
+MODULE_DESCRIPTION("STM TPM I2C ST33 Driver");
+MODULE_VERSION("1.2.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_stm_st33_i2c.h b/drivers/char/tpm/tpm_stm_st33_i2c.h
new file mode 100644
index 0000000..d390542
--- /dev/null
+++ b/drivers/char/tpm/tpm_stm_st33_i2c.h
@@ -0,0 +1,81 @@
+/*
+ * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
+ * Copyright (C) 2009, 2010  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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * STMicroelectronics version 1.2.0, Copyright (C) 2010
+ * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
+ * This is free software, and you are welcome to redistribute it
+ * under certain conditions.
+ *
+ * @Author: Christophe RICARD tpmsupport@st.com
+ *
+ * @File: stm_st33_tpm_i2c.h
+ *
+ * @Date: 09/15/2010
+ */
+#ifndef __STM_ST33_TPM_I2C_MAIN_H__
+#define __STM_ST33_TPM_I2C_MAIN_H__
+
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/sysfs.h>
+#include <linux/gpio.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+#include "tpm.h"
+
+#define MINOR_NUM_I2C		224
+
+#define TPM_ACCESS			(0x0)
+#define TPM_STS				(0x18)
+#define TPM_HASH_END			(0x20)
+#define TPM_DATA_FIFO			(0x24)
+#define TPM_HASH_DATA			(0x24)
+#define TPM_HASH_START			(0x28)
+#define TPM_INTF_CAPABILITY		(0x14)
+#define TPM_INT_STATUS			(0x10)
+#define TPM_INT_ENABLE			(0x08)
+
+#define TPM_DUMMY_BYTE			0xAA
+#define TPM_WRITE_DIRECTION		0x80
+#define TPM_HEADER_SIZE			10
+#define TPM_BUFSIZE			2048
+
+#define LOCALITY0		0
+
+struct st_tpm_hash {
+	int size;
+	u8 *data;
+};
+
+#endif /* __STM_ST33_TPM_I2C_MAIN_H__ */
diff --git a/include/linux/i2c/tpm_stm_st33_i2c.h b/include/linux/i2c/tpm_stm_st33_i2c.h
new file mode 100644
index 0000000..e3ce42d
--- /dev/null
+++ b/include/linux/i2c/tpm_stm_st33_i2c.h
@@ -0,0 +1,47 @@
+/*
+* STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
+* Copyright (C) 2009, 2010 STMicroelectronics
+* Christophe RICARD tpmsupport@st.com
+* 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, write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* STMicroelectronics version 1.2.0, Copyright (C) 2010
+* STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
+* This is free software, and you are welcome to redistribute it
+* under certain conditions.
+*
+* @File: stm_st33_tpm_i2c.h
+*
+* @Date: 06/15/2008
+*/
+#ifndef __STM_ST33_TPM_I2C_H__
+#define __STM_ST33_TPM_I2C_H__
+
+#include <linux/i2c.h>
+
+#define TPM_ST33_I2C			"st33zp24_i2c"
+#define TPM_I2C_ST33_ADDR_WR_LOC0	(0x26 >> 1)
+
+
+struct st33zp24_platform_data {
+	int io_serirq;
+	int io_lpcpd;
+	struct i2c_client *client;
+	bool bChipF;
+	u8 *tpm_i2c_buffer[2]; /* 0 Request 1 Response */
+	struct completion irq_detection;
+	struct mutex lock;
+};
+
+#endif /* __STM_ST33_TPM_I2C_H__ */
-- 
1.7.9.5


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

* Re: [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-11-19 22:15 [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x Mathias Leblanc
  2012-11-19 22:15 ` [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 2.6 Mathias Leblanc
@ 2012-11-26 17:46 ` Kent Yoder
  2012-11-27  8:44   ` Mathias LEBLANC
  1 sibling, 1 reply; 33+ messages in thread
From: Kent Yoder @ 2012-11-26 17:46 UTC (permalink / raw)
  To: Mathias Leblanc
  Cc: Rajiv Andrade, Marcel Selhorst, Sirrix AG, tpmdd-devel,
	Debora Velarde, linux-kernel, Jean-Luc Blanc

Hi Mathias,

On Mon, Nov 19, 2012 at 11:15:21PM +0100, Mathias Leblanc wrote:
>  * STMicroelectronics version 1.2.0, Copyright (C) 2010
>  * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
>  * This is free software, and you are welcome to redistribute it
>  * under certain conditions.
> 
> This is the driver for TPM chip from ST Microelectronics.
> 
> If you have a TPM security chip from STMicroelectronics working with
> an I2C, in menuconfig or .config choose the tpm driver on
> device --> tpm and activate the protocol of your choice before compiling
> the kernel.
> The driver will be accessible from within Linux.
> 
> Tested on linux x86/x64, beagleboard REV B & XM REV C and CHROMIUM OS
> on kernel 3.x.x
> 
> Signed-off-by: Mathias Leblanc <mathias.leblanc@st.com>
> ---
>  drivers/char/tpm/tpm_stm_st33_i2c.c  |  903 ++++++++++++++++++++++++++++++++++
>  drivers/char/tpm/tpm_stm_st33_i2c.h  |   81 +++
>  include/linux/i2c/tpm_stm_st33_i2c.h |   47 ++
>  3 files changed, 1031 insertions(+)
>  create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.c
>  create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.h
>  create mode 100644 include/linux/i2c/tpm_stm_st33_i2c.h

  I'm still getting the compiler errors I mentioned earlier. I've fixed
them up with the patch below (plus some formatting), all except for the
tpm_continue_selftest_nocheck() problem. Do you really need to call
continue selftest on resume?  That strikes me as out of place here.
What's making the call to the TPM to start the self test in that case?

Please test with the patch below.

Thanks,
Kent


diff --git a/drivers/char/tpm/tpm_stm_st33_i2c.c b/drivers/char/tpm/tpm_stm_st33_i2c.c
index 52f3380..67f81b6 100644
--- a/drivers/char/tpm/tpm_stm_st33_i2c.c
+++ b/drivers/char/tpm/tpm_stm_st33_i2c.c
@@ -722,7 +722,7 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
 			goto _irq_set;
 
 		intmask = TPM_GLOBAL_INT_ENABLE;
-		err = I2C_WRITE_DATA(client, TPM_INT_ENABLE + 3, &intmask, 1);
+		err = I2C_WRITE_DATA(client, (TPM_INT_ENABLE + 3), &intmask, 1);
 		if (err < 0)
 			goto _irq_set;
 
@@ -820,10 +820,10 @@ static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
 
 	if (power_mgt)
 		gpio_set_value(pin_infos->io_lpcpd, 0);
-	else{
+	else {
 		if (chip->data_buffer == NULL)
 			chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
-		ret = tpm_pm_suspend(&client->dev, mesg);
+		ret = tpm_pm_suspend(&client->dev);
 	}
 	return ret;
 }				/* tpm_st33_i2c_suspend() */
@@ -848,12 +848,12 @@ static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
 					  (chip->vendor.status(chip) &&
 					  TPM_STS_VALID) == TPM_STS_VALID,
 					  chip->vendor.timeout_b);
-	} else{
-	if (chip->data_buffer == NULL)
-		chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
-	ret = tpm_pm_resume(&client->dev);
-	if (!ret)
-		tpm_continue_selftest_nocheck(chip);
+	} else {
+		if (chip->data_buffer == NULL)
+			chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
+		ret = tpm_pm_resume(&client->dev);
+		if (!ret)
+			tpm_continue_selftest_nocheck(chip);
 	}
 	return ret;
 }				/* tpm_st33_i2c_pm_resume() */


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

* RE: [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-11-26 17:46 ` [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x Kent Yoder
@ 2012-11-27  8:44   ` Mathias LEBLANC
  2012-11-27 14:48     ` [tpmdd-devel] " Kent Yoder
  0 siblings, 1 reply; 33+ messages in thread
From: Mathias LEBLANC @ 2012-11-27  8:44 UTC (permalink / raw)
  To: Kent Yoder
  Cc: Rajiv Andrade, Marcel Selhorst, Sirrix AG, tpmdd-devel,
	Debora Velarde, linux-kernel, Jean-Luc BLANC

Hi Kent,

What's version of the kernel do you compiled?
I don't understand why you have some problem with formating, i have send you the patch with no error and warning of code formating.
The tpm_continue_selftest_nocheck()  (in kernel 3.x.x) and tpm_continue_selftest() (in kernel 2.6.x) is called to have the tpm ready.
If the tpm_continue_selftest is not called by the driver, it will be use in the applications.

Regards,

Matthias Leblanc
________________________________________
From: Kent Yoder [key@linux.vnet.ibm.com]
Sent: 26 November 2012 18:46
To: Mathias LEBLANC
Cc: Rajiv Andrade; Marcel Selhorst; Sirrix AG; tpmdd-devel@lists.sourceforge.net; Debora Velarde; linux-kernel@vger.kernel.org; Jean-Luc BLANC
Subject: Re: [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x

Hi Mathias,

On Mon, Nov 19, 2012 at 11:15:21PM +0100, Mathias Leblanc wrote:
>  * STMicroelectronics version 1.2.0, Copyright (C) 2010
>  * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
>  * This is free software, and you are welcome to redistribute it
>  * under certain conditions.
>
> This is the driver for TPM chip from ST Microelectronics.
>
> If you have a TPM security chip from STMicroelectronics working with
> an I2C, in menuconfig or .config choose the tpm driver on
> device --> tpm and activate the protocol of your choice before compiling
> the kernel.
> The driver will be accessible from within Linux.
>
> Tested on linux x86/x64, beagleboard REV B & XM REV C and CHROMIUM OS
> on kernel 3.x.x
>
> Signed-off-by: Mathias Leblanc <mathias.leblanc@st.com>
> ---
>  drivers/char/tpm/tpm_stm_st33_i2c.c  |  903 ++++++++++++++++++++++++++++++++++
>  drivers/char/tpm/tpm_stm_st33_i2c.h  |   81 +++
>  include/linux/i2c/tpm_stm_st33_i2c.h |   47 ++
>  3 files changed, 1031 insertions(+)
>  create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.c
>  create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.h
>  create mode 100644 include/linux/i2c/tpm_stm_st33_i2c.h

  I'm still getting the compiler errors I mentioned earlier. I've fixed
them up with the patch below (plus some formatting), all except for the
tpm_continue_selftest_nocheck() problem. Do you really need to call
continue selftest on resume?  That strikes me as out of place here.
What's making the call to the TPM to start the self test in that case?

Please test with the patch below.

Thanks,
Kent


diff --git a/drivers/char/tpm/tpm_stm_st33_i2c.c b/drivers/char/tpm/tpm_stm_st33_i2c.c
index 52f3380..67f81b6 100644
--- a/drivers/char/tpm/tpm_stm_st33_i2c.c
+++ b/drivers/char/tpm/tpm_stm_st33_i2c.c
@@ -722,7 +722,7 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
                        goto _irq_set;

                intmask = TPM_GLOBAL_INT_ENABLE;
-               err = I2C_WRITE_DATA(client, TPM_INT_ENABLE + 3, &intmask, 1);
+               err = I2C_WRITE_DATA(client, (TPM_INT_ENABLE + 3), &intmask, 1);
                if (err < 0)
                        goto _irq_set;

@@ -820,10 +820,10 @@ static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)

        if (power_mgt)
                gpio_set_value(pin_infos->io_lpcpd, 0);
-       else{
+       else {
                if (chip->data_buffer == NULL)
                        chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
-               ret = tpm_pm_suspend(&client->dev, mesg);
+               ret = tpm_pm_suspend(&client->dev);
        }
        return ret;
 }                              /* tpm_st33_i2c_suspend() */
@@ -848,12 +848,12 @@ static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
                                          (chip->vendor.status(chip) &&
                                          TPM_STS_VALID) == TPM_STS_VALID,
                                          chip->vendor.timeout_b);
-       } else{
-       if (chip->data_buffer == NULL)
-               chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
-       ret = tpm_pm_resume(&client->dev);
-       if (!ret)
-               tpm_continue_selftest_nocheck(chip);
+       } else {
+               if (chip->data_buffer == NULL)
+                       chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
+               ret = tpm_pm_resume(&client->dev);
+               if (!ret)
+                       tpm_continue_selftest_nocheck(chip);
        }
        return ret;
 }                              /* tpm_st33_i2c_pm_resume() */

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

* Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-11-27  8:44   ` Mathias LEBLANC
@ 2012-11-27 14:48     ` Kent Yoder
  2012-11-28  8:54       ` Mathias LEBLANC
  0 siblings, 1 reply; 33+ messages in thread
From: Kent Yoder @ 2012-11-27 14:48 UTC (permalink / raw)
  To: Mathias LEBLANC
  Cc: Kent Yoder, Jean-Luc BLANC, linux-kernel, Rajiv Andrade,
	tpmdd-devel, Sirrix AG

On Tue, Nov 27, 2012 at 2:44 AM, Mathias LEBLANC <Mathias.LEBLANC@st.com> wrote:
> Hi Kent,
>
> What's version of the kernel do you compiled?
> I don't understand why you have some problem with formating, i have send you the patch with no error and warning of code formating.
> The tpm_continue_selftest_nocheck()  (in kernel 3.x.x) and tpm_continue_selftest() (in kernel 2.6.x) is called to have the tpm ready.
> If the tpm_continue_selftest is not called by the driver, it will be use in the applications.

Apply against this tree's "next" branch.

git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git

Thanks,
Kent

> Regards,
>
> Matthias Leblanc
> ________________________________________
> From: Kent Yoder [key@linux.vnet.ibm.com]
> Sent: 26 November 2012 18:46
> To: Mathias LEBLANC
> Cc: Rajiv Andrade; Marcel Selhorst; Sirrix AG; tpmdd-devel@lists.sourceforge.net; Debora Velarde; linux-kernel@vger.kernel.org; Jean-Luc BLANC
> Subject: Re: [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
>
> Hi Mathias,
>
> On Mon, Nov 19, 2012 at 11:15:21PM +0100, Mathias Leblanc wrote:
>>  * STMicroelectronics version 1.2.0, Copyright (C) 2010
>>  * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
>>  * This is free software, and you are welcome to redistribute it
>>  * under certain conditions.
>>
>> This is the driver for TPM chip from ST Microelectronics.
>>
>> If you have a TPM security chip from STMicroelectronics working with
>> an I2C, in menuconfig or .config choose the tpm driver on
>> device --> tpm and activate the protocol of your choice before compiling
>> the kernel.
>> The driver will be accessible from within Linux.
>>
>> Tested on linux x86/x64, beagleboard REV B & XM REV C and CHROMIUM OS
>> on kernel 3.x.x
>>
>> Signed-off-by: Mathias Leblanc <mathias.leblanc@st.com>
>> ---
>>  drivers/char/tpm/tpm_stm_st33_i2c.c  |  903 ++++++++++++++++++++++++++++++++++
>>  drivers/char/tpm/tpm_stm_st33_i2c.h  |   81 +++
>>  include/linux/i2c/tpm_stm_st33_i2c.h |   47 ++
>>  3 files changed, 1031 insertions(+)
>>  create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.c
>>  create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.h
>>  create mode 100644 include/linux/i2c/tpm_stm_st33_i2c.h
>
>   I'm still getting the compiler errors I mentioned earlier. I've fixed
> them up with the patch below (plus some formatting), all except for the
> tpm_continue_selftest_nocheck() problem. Do you really need to call
> continue selftest on resume?  That strikes me as out of place here.
> What's making the call to the TPM to start the self test in that case?
>
> Please test with the patch below.
>
> Thanks,
> Kent
>
>
> diff --git a/drivers/char/tpm/tpm_stm_st33_i2c.c b/drivers/char/tpm/tpm_stm_st33_i2c.c
> index 52f3380..67f81b6 100644
> --- a/drivers/char/tpm/tpm_stm_st33_i2c.c
> +++ b/drivers/char/tpm/tpm_stm_st33_i2c.c
> @@ -722,7 +722,7 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
>                         goto _irq_set;
>
>                 intmask = TPM_GLOBAL_INT_ENABLE;
> -               err = I2C_WRITE_DATA(client, TPM_INT_ENABLE + 3, &intmask, 1);
> +               err = I2C_WRITE_DATA(client, (TPM_INT_ENABLE + 3), &intmask, 1);
>                 if (err < 0)
>                         goto _irq_set;
>
> @@ -820,10 +820,10 @@ static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
>
>         if (power_mgt)
>                 gpio_set_value(pin_infos->io_lpcpd, 0);
> -       else{
> +       else {
>                 if (chip->data_buffer == NULL)
>                         chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
> -               ret = tpm_pm_suspend(&client->dev, mesg);
> +               ret = tpm_pm_suspend(&client->dev);
>         }
>         return ret;
>  }                              /* tpm_st33_i2c_suspend() */
> @@ -848,12 +848,12 @@ static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
>                                           (chip->vendor.status(chip) &&
>                                           TPM_STS_VALID) == TPM_STS_VALID,
>                                           chip->vendor.timeout_b);
> -       } else{
> -       if (chip->data_buffer == NULL)
> -               chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
> -       ret = tpm_pm_resume(&client->dev);
> -       if (!ret)
> -               tpm_continue_selftest_nocheck(chip);
> +       } else {
> +               if (chip->data_buffer == NULL)
> +                       chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
> +               ret = tpm_pm_resume(&client->dev);
> +               if (!ret)
> +                       tpm_continue_selftest_nocheck(chip);
>         }
>         return ret;
>  }                              /* tpm_st33_i2c_pm_resume() */
>
> ------------------------------------------------------------------------------
> Monitor your physical, virtual and cloud infrastructure from a single
> web console. Get in-depth insight into apps, servers, databases, vmware,
> SAP, cloud infrastructure, etc. Download 30-day Free Trial.
> Pricing starts from $795 for 25 servers or applications!
> http://p.sf.net/sfu/zoho_dev2dev_nov
> _______________________________________________
> tpmdd-devel mailing list
> tpmdd-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/tpmdd-devel



-- 
IBM LTC Security

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

* RE: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-11-27 14:48     ` [tpmdd-devel] " Kent Yoder
@ 2012-11-28  8:54       ` Mathias LEBLANC
  2012-11-28 15:31         ` Kent Yoder
  0 siblings, 1 reply; 33+ messages in thread
From: Mathias LEBLANC @ 2012-11-28  8:54 UTC (permalink / raw)
  To: Kent Yoder
  Cc: Kent Yoder, Jean-Luc BLANC, linux-kernel, Rajiv Andrade,
	tpmdd-devel, Sirrix AG

Hi Kent,

I have been tried the patch on your linux branch and indeed, i have an error about tpm_continue_seftest.
What is the kernel I should use to test officially my patch? Because i saw a lot of different version of linux kernel with the tpm_continue_seftest function.
I used this repo git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 for my tests.

Matthias Leblanc

________________________________________From: Kent Yoder [shpedoikal@gmail.com]
Sent: 27 November 2012 15:48
To: Mathias LEBLANC
Cc: Kent Yoder; Jean-Luc BLANC; linux-kernel@vger.kernel.org; Rajiv Andrade; tpmdd-devel@lists.sourceforge.net; Sirrix AG
Subject: Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x

On Tue, Nov 27, 2012 at 2:44 AM, Mathias LEBLANC <Mathias.LEBLANC@st.com> wrote:
> Hi Kent,
>
> What's version of the kernel do you compiled?
> I don't understand why you have some problem with formating, i have send you the patch with no error and warning of code formating.
> The tpm_continue_selftest_nocheck()  (in kernel 3.x.x) and tpm_continue_selftest() (in kernel 2.6.x) is called to have the tpm ready.
> If the tpm_continue_selftest is not called by the driver, it will be use in the applications.

Apply against this tree's "next" branch.

git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git

Thanks,
Kent

> Regards,
>
> Matthias Leblanc
> ________________________________________
> From: Kent Yoder [key@linux.vnet.ibm.com]
> Sent: 26 November 2012 18:46
> To: Mathias LEBLANC
> Cc: Rajiv Andrade; Marcel Selhorst; Sirrix AG; tpmdd-devel@lists.sourceforge.net; Debora Velarde; linux-kernel@vger.kernel.org; Jean-Luc BLANC
> Subject: Re: [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
>
> Hi Mathias,
>
> On Mon, Nov 19, 2012 at 11:15:21PM +0100, Mathias Leblanc wrote:
>>  * STMicroelectronics version 1.2.0, Copyright (C) 2010
>>  * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
>>  * This is free software, and you are welcome to redistribute it
>>  * under certain conditions.
>
>> This is the driver for TPM chip from ST Microelectronics.
>>
>> If you have a TPM security chip from STMicroelectronics working with
>> an I2C, in menuconfig or .config choose the tpm driver on
>> device --> tpm and activate the protocol of your choice before compiling
>> the kernel.
>> The driver will be accessible from within Linux.
>>
>> Tested on linux x86/x64, beagleboard REV B & XM REV C and CHROMIUM OS
>> on kernel 3.x.x
>>
>> Signed-off-by: Mathias Leblanc <mathias.leblanc@st.com>
>> ---
>>  drivers/char/tpm/tpm_stm_st33_i2c.c  |  903 ++++++++++++++++++++++++++++++++++
>>  drivers/char/tpm/tpm_stm_st33_i2c.h  |   81 +++
>>  include/linux/i2c/tpm_stm_st33_i2c.h |   47 ++
>>  3 files changed, 1031 insertions(+)
>>  create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.c
>>  create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.h
>>  create mode 100644 include/linux/i2c/tpm_stm_st33_i2c.h
>
>   I'm still getting the compiler errors I mentioned earlier. I've fixed
> them up with the patch below (plus some formatting), all except for the
> tpm_continue_selftest_nocheck() problem. Do you really need to call
> continue selftest on resume?  That strikes me as out of place here.
> What's making the call to the TPM to start the self test in that case?
>
> Please test with the patch below.
>
> Thanks,
> Kent
>
>
> diff --git a/drivers/char/tpm/tpm_stm_st33_i2c.c b/drivers/char/tpm/tpm_stm_st33_i2c.c
> index 52f3380..67f81b6 100644
> --- a/drivers/char/tpm/tpm_stm_st33_i2c.c
> +++ b/drivers/char/tpm/tpm_stm_st33_i2c.c
> @@ -722,7 +722,7 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
>                         goto _irq_set;
>
>                 intmask = TPM_GLOBAL_INT_ENABLE;
> -               err = I2C_WRITE_DATA(client, TPM_INT_ENABLE + 3, &intmask, 1);
> +               err = I2C_WRITE_DATA(client, (TPM_INT_ENABLE + 3), &intmask, 1);
>                 if (err < 0)
>                         goto _irq_set;
>
> @@ -820,10 +820,10 @@ static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
>
>         if (power_mgt)
>                 gpio_set_value(pin_infos->io_lpcpd, 0);
> -       else{
> +       else {
>                 if (chip->data_buffer == NULL)
>                         chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
> -               ret = tpm_pm_suspend(&client->dev, mesg);
> +               ret = tpm_pm_suspend(&client->dev);
>         }
>         return ret;
>  }                              /* tpm_st33_i2c_suspend() */
> @@ -848,12 +848,12 @@ static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
>                                           (chip->vendor.status(chip) &&
>                                           TPM_STS_VALID) == TPM_STS_VALID,
>                                           chip->vendor.timeout_b);
> -       } else{
> -       if (chip->data_buffer == NULL)
> -               chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
> -       ret = tpm_pm_resume(&client->dev);
> -       if (!ret)
> -               tpm_continue_selftest_nocheck(chip);
> +       } else {
> +               if (chip->data_buffer == NULL)
> +                       chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
> +               ret = tpm_pm_resume(&client->dev);
> +               if (!ret)
> +                       tpm_continue_selftest_nocheck(chip);
>         }
>         return ret;
>  }                              /* tpm_st33_i2c_pm_resume() */
>
> ------------------------------------------------------------------------------
> Monitor your physical, virtual and cloud infrastructure from a single
> web console. Get in-depth insight into apps, servers, databases, vmware,
> SAP, cloud infrastructure, etc. Download 30-day Free Trial.
> Pricing starts from $795 for 25 servers or applications!
> http://p.sf.net/sfu/zoho_dev2dev_nov
> _______________________________________________
> tpmdd-devel mailing list
> tpmdd-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/tpmdd-devel



--
IBM LTC Security

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

* Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-11-28  8:54       ` Mathias LEBLANC
@ 2012-11-28 15:31         ` Kent Yoder
  2012-11-28 17:48           ` Mathias LEBLANC
  0 siblings, 1 reply; 33+ messages in thread
From: Kent Yoder @ 2012-11-28 15:31 UTC (permalink / raw)
  To: Mathias LEBLANC
  Cc: Kent Yoder, Jean-Luc BLANC, linux-kernel, Rajiv Andrade,
	tpmdd-devel, Sirrix AG

On Wed, Nov 28, 2012 at 2:54 AM, Mathias LEBLANC <Mathias.LEBLANC@st.com> wrote:
> Hi Kent,
>
> I have been tried the patch on your linux branch and indeed, i have an error about tpm_continue_seftest.
> What is the kernel I should use to test officially my patch? Because i saw a lot of different version of linux kernel with the tpm_continue_seftest function.
> I used this repo git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 for my tests.

  The tree url I sent you is the correct one. Make sure you use the
"next" branch.

Kent

> Matthias Leblanc
>
> ________________________________________From: Kent Yoder [shpedoikal@gmail.com]
> Sent: 27 November 2012 15:48
> To: Mathias LEBLANC
> Cc: Kent Yoder; Jean-Luc BLANC; linux-kernel@vger.kernel.org; Rajiv Andrade; tpmdd-devel@lists.sourceforge.net; Sirrix AG
> Subject: Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
>
> On Tue, Nov 27, 2012 at 2:44 AM, Mathias LEBLANC <Mathias.LEBLANC@st.com> wrote:
>> Hi Kent,
>>
>> What's version of the kernel do you compiled?
>> I don't understand why you have some problem with formating, i have send you the patch with no error and warning of code formating.
>> The tpm_continue_selftest_nocheck()  (in kernel 3.x.x) and tpm_continue_selftest() (in kernel 2.6.x) is called to have the tpm ready.
>> If the tpm_continue_selftest is not called by the driver, it will be use in the applications.
>
> Apply against this tree's "next" branch.
>
> git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git
>
> Thanks,
> Kent
>
>> Regards,
>>
>> Matthias Leblanc
>> ________________________________________
>> From: Kent Yoder [key@linux.vnet.ibm.com]
>> Sent: 26 November 2012 18:46
>> To: Mathias LEBLANC
>> Cc: Rajiv Andrade; Marcel Selhorst; Sirrix AG; tpmdd-devel@lists.sourceforge.net; Debora Velarde; linux-kernel@vger.kernel.org; Jean-Luc BLANC
>> Subject: Re: [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
>>
>> Hi Mathias,
>>
>> On Mon, Nov 19, 2012 at 11:15:21PM +0100, Mathias Leblanc wrote:
>>>  * STMicroelectronics version 1.2.0, Copyright (C) 2010
>>>  * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
>>>  * This is free software, and you are welcome to redistribute it
>>>  * under certain conditions.
>>
>>> This is the driver for TPM chip from ST Microelectronics.
>>>
>>> If you have a TPM security chip from STMicroelectronics working with
>>> an I2C, in menuconfig or .config choose the tpm driver on
>>> device --> tpm and activate the protocol of your choice before compiling
>>> the kernel.
>>> The driver will be accessible from within Linux.
>>>
>>> Tested on linux x86/x64, beagleboard REV B & XM REV C and CHROMIUM OS
>>> on kernel 3.x.x
>>>
>>> Signed-off-by: Mathias Leblanc <mathias.leblanc@st.com>
>>> ---
>>>  drivers/char/tpm/tpm_stm_st33_i2c.c  |  903 ++++++++++++++++++++++++++++++++++
>>>  drivers/char/tpm/tpm_stm_st33_i2c.h  |   81 +++
>>>  include/linux/i2c/tpm_stm_st33_i2c.h |   47 ++
>>>  3 files changed, 1031 insertions(+)
>>>  create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.c
>>>  create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.h
>>>  create mode 100644 include/linux/i2c/tpm_stm_st33_i2c.h
>>
>>   I'm still getting the compiler errors I mentioned earlier. I've fixed
>> them up with the patch below (plus some formatting), all except for the
>> tpm_continue_selftest_nocheck() problem. Do you really need to call
>> continue selftest on resume?  That strikes me as out of place here.
>> What's making the call to the TPM to start the self test in that case?
>>
>> Please test with the patch below.
>>
>> Thanks,
>> Kent
>>
>>
>> diff --git a/drivers/char/tpm/tpm_stm_st33_i2c.c b/drivers/char/tpm/tpm_stm_st33_i2c.c
>> index 52f3380..67f81b6 100644
>> --- a/drivers/char/tpm/tpm_stm_st33_i2c.c
>> +++ b/drivers/char/tpm/tpm_stm_st33_i2c.c
>> @@ -722,7 +722,7 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
>>                         goto _irq_set;
>>
>>                 intmask = TPM_GLOBAL_INT_ENABLE;
>> -               err = I2C_WRITE_DATA(client, TPM_INT_ENABLE + 3, &intmask, 1);
>> +               err = I2C_WRITE_DATA(client, (TPM_INT_ENABLE + 3), &intmask, 1);
>>                 if (err < 0)
>>                         goto _irq_set;
>>
>> @@ -820,10 +820,10 @@ static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
>>
>>         if (power_mgt)
>>                 gpio_set_value(pin_infos->io_lpcpd, 0);
>> -       else{
>> +       else {
>>                 if (chip->data_buffer == NULL)
>>                         chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
>> -               ret = tpm_pm_suspend(&client->dev, mesg);
>> +               ret = tpm_pm_suspend(&client->dev);
>>         }
>>         return ret;
>>  }                              /* tpm_st33_i2c_suspend() */
>> @@ -848,12 +848,12 @@ static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
>>                                           (chip->vendor.status(chip) &&
>>                                           TPM_STS_VALID) == TPM_STS_VALID,
>>                                           chip->vendor.timeout_b);
>> -       } else{
>> -       if (chip->data_buffer == NULL)
>> -               chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
>> -       ret = tpm_pm_resume(&client->dev);
>> -       if (!ret)
>> -               tpm_continue_selftest_nocheck(chip);
>> +       } else {
>> +               if (chip->data_buffer == NULL)
>> +                       chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
>> +               ret = tpm_pm_resume(&client->dev);
>> +               if (!ret)
>> +                       tpm_continue_selftest_nocheck(chip);
>>         }
>>         return ret;
>>  }                              /* tpm_st33_i2c_pm_resume() */
>>
>> ------------------------------------------------------------------------------
>> Monitor your physical, virtual and cloud infrastructure from a single
>> web console. Get in-depth insight into apps, servers, databases, vmware,
>> SAP, cloud infrastructure, etc. Download 30-day Free Trial.
>> Pricing starts from $795 for 25 servers or applications!
>> http://p.sf.net/sfu/zoho_dev2dev_nov
>> _______________________________________________
>> tpmdd-devel mailing list
>> tpmdd-devel@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/tpmdd-devel
>
>
>
> --
> IBM LTC Security



-- 
IBM LTC Security

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

* RE: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-11-28 15:31         ` Kent Yoder
@ 2012-11-28 17:48           ` Mathias LEBLANC
  2012-11-28 19:04             ` Kent Yoder
  2012-11-29  0:04             ` Peter Hüwe
  0 siblings, 2 replies; 33+ messages in thread
From: Mathias LEBLANC @ 2012-11-28 17:48 UTC (permalink / raw)
  To: Kent Yoder
  Cc: Kent Yoder, Jean-Luc BLANC, linux-kernel, Rajiv Andrade,
	tpmdd-devel, Sirrix AG

[-- Attachment #1: Type: text/plain, Size: 7243 bytes --]

Ok, so i have patch the ST33 I2C driver on this branch and correct some errors.
I send you the patch for the kernel 3.x 
I have no error on compilation, tell me if you have problems.
I have implemented the tpm_do_selftest function to get the tpm ready, but it can be removed
________________________________________
From: Kent Yoder [shpedoikal@gmail.com]
Sent: 28 November 2012 16:31
To: Mathias LEBLANC
Cc: Kent Yoder; Jean-Luc BLANC; linux-kernel@vger.kernel.org; Rajiv Andrade; tpmdd-devel@lists.sourceforge.net; Sirrix AG
Subject: Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x

On Wed, Nov 28, 2012 at 2:54 AM, Mathias LEBLANC <Mathias.LEBLANC@st.com> wrote:
> Hi Kent,
>
> I have been tried the patch on your linux branch and indeed, i have an error about tpm_continue_seftest.
> What is the kernel I should use to test officially my patch? Because i saw a lot of different version of linux kernel with the tpm_continue_seftest function.
> I used this repo git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 for my tests.

  The tree url I sent you is the correct one. Make sure you use the
"next" branch.

Kent

> Matthias Leblanc
>
> ________________________________________From: Kent Yoder [shpedoikal@gmail.com]
> Sent: 27 November 2012 15:48
> To: Mathias LEBLANC
> Cc: Kent Yoder; Jean-Luc BLANC; linux-kernel@vger.kernel.org; Rajiv Andrade; tpmdd-devel@lists.sourceforge.net; Sirrix AG
> Subject: Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
>
> On Tue, Nov 27, 2012 at 2:44 AM, Mathias LEBLANC <Mathias.LEBLANC@st.com> wrote:
>> Hi Kent,
>>
>> What's version of the kernel do you compiled?
>> I don't understand why you have some problem with formating, i have send you the patch with no error and warning of code formating.
>> The tpm_continue_selftest_nocheck()  (in kernel 3.x.x) and tpm_continue_selftest() (in kernel 2.6.x) is called to have the tpm ready.
>> If the tpm_continue_selftest is not called by the driver, it will be use in the applications.
>
> Apply against this tree's "next" branch.
>
> git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git
>
> Thanks,
> Kent
>
>> Regards,
>>
>> Matthias Leblanc
>> ________________________________________
>> From: Kent Yoder [key@linux.vnet.ibm.com]
>> Sent: 26 November 2012 18:46
>> To: Mathias LEBLANC
>> Cc: Rajiv Andrade; Marcel Selhorst; Sirrix AG; tpmdd-devel@lists.sourceforge.net; Debora Velarde; linux-kernel@vger.kernel.org; Jean-Luc BLANC
>> Subject: Re: [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
>>
>> Hi Mathias,
>>
>> On Mon, Nov 19, 2012 at 11:15:21PM +0100, Mathias Leblanc wrote:
>>>  * STMicroelectronics version 1.2.0, Copyright (C) 2010
>>>  * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
>>>  * This is free software, and you are welcome to redistribute it
>>>  * under certain conditions.
>>
>>> This is the driver for TPM chip from ST Microelectronics.
>>>
>>> If you have a TPM security chip from STMicroelectronics working with
>>> an I2C, in menuconfig or .config choose the tpm driver on
>>> device --> tpm and activate the protocol of your choice before compiling
>>> the kernel.
>>> The driver will be accessible from within Linux.
>>>
>>> Tested on linux x86/x64, beagleboard REV B & XM REV C and CHROMIUM OS
>>> on kernel 3.x.x
>>>
>>> Signed-off-by: Mathias Leblanc <mathias.leblanc@st.com>
>>> ---
>>>  drivers/char/tpm/tpm_stm_st33_i2c.c  |  903 ++++++++++++++++++++++++++++++++++
>>>  drivers/char/tpm/tpm_stm_st33_i2c.h  |   81 +++
>>>  include/linux/i2c/tpm_stm_st33_i2c.h |   47 ++
>>>  3 files changed, 1031 insertions(+)
>>>  create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.c
>>>  create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.h
>>>  create mode 100644 include/linux/i2c/tpm_stm_st33_i2c.h
>>
>>   I'm still getting the compiler errors I mentioned earlier. I've fixed
>> them up with the patch below (plus some formatting), all except for the
>> tpm_continue_selftest_nocheck() problem. Do you really need to call
>> continue selftest on resume?  That strikes me as out of place here.
>> What's making the call to the TPM to start the self test in that case?
>>
>> Please test with the patch below.
>>
>> Thanks,
>> Kent
>>
>>
>> diff --git a/drivers/char/tpm/tpm_stm_st33_i2c.c b/drivers/char/tpm/tpm_stm_st33_i2c.c
>> index 52f3380..67f81b6 100644
>> --- a/drivers/char/tpm/tpm_stm_st33_i2c.c
>> +++ b/drivers/char/tpm/tpm_stm_st33_i2c.c
>> @@ -722,7 +722,7 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
>>                         goto _irq_set;
>>
>>                 intmask = TPM_GLOBAL_INT_ENABLE;
>> -               err = I2C_WRITE_DATA(client, TPM_INT_ENABLE + 3, &intmask, 1);
>> +               err = I2C_WRITE_DATA(client, (TPM_INT_ENABLE + 3), &intmask, 1);
>>                 if (err < 0)
>>                         goto _irq_set;
>>
>> @@ -820,10 +820,10 @@ static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
>>
>>         if (power_mgt)
>>                 gpio_set_value(pin_infos->io_lpcpd, 0);
>> -       else{
>> +       else {
>>                 if (chip->data_buffer == NULL)
>>                         chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
>> -               ret = tpm_pm_suspend(&client->dev, mesg);
>> +               ret = tpm_pm_suspend(&client->dev);
>>         }
>>         return ret;
>>  }                              /* tpm_st33_i2c_suspend() */
>> @@ -848,12 +848,12 @@ static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
>>                                           (chip->vendor.status(chip) &&
>>                                           TPM_STS_VALID) == TPM_STS_VALID,
>>                                           chip->vendor.timeout_b);
>> -       } else{
>> -       if (chip->data_buffer == NULL)
>> -               chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
>> -       ret = tpm_pm_resume(&client->dev);
>> -       if (!ret)
>> -               tpm_continue_selftest_nocheck(chip);
>> +       } else {
>> +               if (chip->data_buffer == NULL)
>> +                       chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
>> +               ret = tpm_pm_resume(&client->dev);
>> +               if (!ret)
>> +                       tpm_continue_selftest_nocheck(chip);
>>         }
>>         return ret;
>>  }                              /* tpm_st33_i2c_pm_resume() */
>>
>> ------------------------------------------------------------------------------
>> Monitor your physical, virtual and cloud infrastructure from a single
>> web console. Get in-depth insight into apps, servers, databases, vmware,
>> SAP, cloud infrastructure, etc. Download 30-day Free Trial.
>> Pricing starts from $795 for 25 servers or applications!
>> http://p.sf.net/sfu/zoho_dev2dev_nov
>> _______________________________________________
>> tpmdd-devel mailing list
>> tpmdd-devel@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/tpmdd-devel
>
>
>
> --
> IBM LTC Security



--
IBM LTC Security

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-TPM-STMicroelectronics-ST33-I2C-KERNEL-3.x.patch --]
[-- Type: text/x-patch; name="0001-TPM-STMicroelectronics-ST33-I2C-KERNEL-3.x.patch", Size: 30813 bytes --]

From 3cf4687665a0bcffe89de92416f0d5886a90100f Mon Sep 17 00:00:00 2001
From: Mathias Leblanc <mathias.leblanc@st.com>
Date: Wed, 28 Nov 2012 18:22:24 +0100
Subject: [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x

 * STMicroelectronics version 1.2.0, Copyright (C) 2010
 * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
 * This is free software, and you are welcome to redistribute it
 * under certain conditions.

This is the driver for TPM chip from ST Microelectronics.

If you have a TPM security chip from STMicroelectronics working with
an I2C, in menuconfig or .config choose the tpm driver on
device --> tpm and activate the protocol of your choice before compiling
the kernel.
The driver will be accessible from within Linux.

Tested on linux x86/x64 on kernel 3.x

Signed-off-by: Mathias Leblanc <mathias.leblanc@st.com>
---
 drivers/char/tpm/tpm_stm_st33_i2c.c  |  903 ++++++++++++++++++++++++++++++++++
 drivers/char/tpm/tpm_stm_st33_i2c.h  |   81 +++
 include/linux/i2c/tpm_stm_st33_i2c.h |   47 ++
 3 files changed, 1031 insertions(+)
 create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.c
 create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.h
 create mode 100644 include/linux/i2c/tpm_stm_st33_i2c.h

diff --git a/drivers/char/tpm/tpm_stm_st33_i2c.c b/drivers/char/tpm/tpm_stm_st33_i2c.c
new file mode 100644
index 0000000..32cdd5e
--- /dev/null
+++ b/drivers/char/tpm/tpm_stm_st33_i2c.c
@@ -0,0 +1,903 @@
+/*
+ * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
+ * Copyright (C) 2009, 2010  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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * STMicroelectronics version 1.2.0, Copyright (C) 2010
+ * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
+ * This is free software, and you are welcome to redistribute it
+ * under certain conditions.
+ *
+ * @Author: Christophe RICARD tpmsupport@st.com
+ *
+ * @File: tpm_stm_st33_i2c.c
+ *
+ * @Synopsis:
+ *	09/15/2010:	First shot driver tpm_tis driver for
+			 lpc is used as model.
+ */
+
+#include <linux/i2c/tpm_stm_st33_i2c.h>
+
+#include "tpm_stm_st33_i2c.h"
+
+enum stm33zp24_access {
+	TPM_ACCESS_VALID = 0x80,
+	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
+	TPM_ACCESS_REQUEST_PENDING = 0x04,
+	TPM_ACCESS_REQUEST_USE = 0x02,
+};
+
+enum stm33zp24_status {
+	TPM_STS_VALID = 0x80,
+	TPM_STS_COMMAND_READY = 0x40,
+	TPM_STS_GO = 0x20,
+	TPM_STS_DATA_AVAIL = 0x10,
+	TPM_STS_DATA_EXPECT = 0x08,
+};
+
+enum stm33zp24_int_flags {
+	TPM_GLOBAL_INT_ENABLE = 0x80,
+	TPM_INTF_CMD_READY_INT = 0x080,
+	TPM_INTF_FIFO_AVALAIBLE_INT = 0x040,
+	TPM_INTF_WAKE_UP_READY_INT = 0x020,
+	TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
+	TPM_INTF_STS_VALID_INT = 0x002,
+	TPM_INTF_DATA_AVAIL_INT = 0x001,
+};
+
+enum tis_defaults {
+	TIS_SHORT_TIMEOUT = 750,
+	TIS_LONG_TIMEOUT = 2000,
+};
+
+/*
+ * write8_reg
+ * Send byte to the TIS register according to the ST33ZP24 I2C protocol.
+ * @param: tpm_register, the tpm tis register where the data should be written
+ * @param: tpm_data, the tpm_data to write inside the tpm_register
+ * @param: tpm_size, The length of the data
+ * @return: Returns negative errno, or else the number of bytes written.
+ */
+static int write8_reg(struct i2c_client *client, u8 tpm_register,
+		      u8 *tpm_data, u16 tpm_size)
+{
+	u8 data;
+	int value = 0;
+	struct st33zp24_platform_data *pin_infos;
+
+	pin_infos = client->dev.platform_data;
+
+	data = tpm_register;
+	memcpy(pin_infos->tpm_i2c_buffer[0], &data, sizeof(data));
+	memcpy(pin_infos->tpm_i2c_buffer[0] + 1, tpm_data, tpm_size);
+	value = i2c_master_send(client, pin_infos->tpm_i2c_buffer[0],
+				tpm_size + 1);
+	return value;
+} /* write8_reg() */
+
+/*
+ * read8_reg
+ * Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
+ * @param: tpm_register, the tpm tis register where the data should be read
+ * @param: tpm_data, the TPM response
+ * @param: tpm_size, tpm TPM response size to read.
+ * @return: number of byte read successfully: should be one if success.
+ */
+static int read8_reg(struct i2c_client *client, u8 tpm_register,
+		    u8 *tpm_data, int tpm_size)
+{
+	u8 status = 0;
+	u8 data;
+	struct st33zp24_platform_data *pin_infos;
+
+	pin_infos = client->dev.platform_data;
+
+	data = TPM_DUMMY_BYTE;
+	status = write8_reg(client, tpm_register, &data, 1);
+	if (status == 2)
+		status = i2c_master_recv(client, tpm_data, tpm_size);
+	return status;
+} /* read8_reg() */
+
+/*
+ * I2C_WRITE_DATA
+ * Send byte to the TIS register according to the ST33ZP24 I2C protocol.
+ * @param: client, the chip description
+ * @param: tpm_register, the tpm tis register where the data should be written
+ * @param: tpm_data, the tpm_data to write inside the tpm_register
+ * @param: tpm_size, The length of the data
+ * @return: number of byte written successfully: should be one if success.
+ */
+#define I2C_WRITE_DATA(client, tpm_register, tpm_data, tpm_size) \
+	(write8_reg(client, tpm_register | \
+	TPM_WRITE_DIRECTION, tpm_data, tpm_size))
+
+/*
+ * I2C_READ_DATA
+ * Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
+ * @param: tpm, the chip description
+ * @param: tpm_register, the tpm tis register where the data should be read
+ * @param: tpm_data, the TPM response
+ * @param: tpm_size, tpm TPM response size to read.
+ * @return: number of byte read successfully: should be one if success.
+ */
+#define I2C_READ_DATA(client, tpm_register, tpm_data, tpm_size) \
+	(read8_reg(client, tpm_register, tpm_data, tpm_size))
+
+/*
+ * clear_interruption
+ * clear the TPM interrupt register.
+ * @param: tpm, the chip description
+ */
+static void clear_interruption(struct i2c_client *client)
+{
+	u8 interrupt;
+	I2C_READ_DATA(client, TPM_INT_STATUS, &interrupt, 1);
+	I2C_WRITE_DATA(client, TPM_INT_STATUS, &interrupt, 1);
+	I2C_READ_DATA(client, TPM_INT_STATUS, &interrupt, 1);
+} /* clear_interruption() */
+
+/*
+ * _wait_for_interrupt_serirq_timeout
+ * @param: tpm, the chip description
+ * @param: timeout, the timeout of the interrupt
+ * @return: the status of the interruption.
+ */
+static long _wait_for_interrupt_serirq_timeout(struct tpm_chip *chip,
+						unsigned long timeout)
+{
+	long status;
+	struct i2c_client *client;
+	struct st33zp24_platform_data *pin_infos;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+	pin_infos = client->dev.platform_data;
+
+	status = wait_for_completion_interruptible_timeout(
+					&pin_infos->irq_detection,
+						timeout);
+	if (status > 0)
+		enable_irq(gpio_to_irq(pin_infos->io_serirq));
+	gpio_direction_input(pin_infos->io_serirq);
+
+	return status;
+} /* wait_for_interrupt_serirq_timeout() */
+
+int wait_for_serirq_timeout(struct tpm_chip *chip, bool condition,
+				 unsigned long timeout)
+{
+	int status = 2;
+	struct i2c_client *client;
+	struct st33zp24_platform_data *pin_infos;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+	pin_infos = client->dev.platform_data;
+
+	status = _wait_for_interrupt_serirq_timeout(chip, timeout);
+	if (!status) {
+		status = -EBUSY;
+	} else{
+		clear_interruption(client);
+		if (condition)
+			status = 1;
+	}
+	return status;
+}
+
+/*
+ * tpm_stm_i2c_cancel, cancel is not implemented.
+ * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h
+ */
+static void tpm_stm_i2c_cancel(struct tpm_chip *chip)
+{
+	struct i2c_client *client;
+	u8 data;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+
+	data = TPM_STS_COMMAND_READY;
+	I2C_WRITE_DATA(client, TPM_STS, &data, 1);
+	if (chip->vendor.irq)
+		wait_for_serirq_timeout(chip, 1, chip->vendor.timeout_a);
+}	/* tpm_stm_i2c_cancel() */
+
+/*
+ * tpm_stm_spi_status return the TPM_STS register
+ * @param: chip, the tpm chip description
+ * @return: the TPM_STS register value.
+ */
+static u8 tpm_stm_i2c_status(struct tpm_chip *chip)
+{
+	struct i2c_client *client;
+	u8 data;
+	client = (struct i2c_client *) chip->vendor.iobase;
+
+	I2C_READ_DATA(client, TPM_STS, &data, 1);
+	return data;
+}				/* tpm_stm_i2c_status() */
+
+
+/*
+ * check_locality if the locality is active
+ * @param: chip, the tpm chip description
+ * @return: the active locality or -EACCESS.
+ */
+static int check_locality(struct tpm_chip *chip)
+{
+	struct i2c_client *client;
+	u8 data;
+	u8 status;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+
+	status = I2C_READ_DATA(client, TPM_ACCESS, &data, 1);
+	if (status && (data &
+		(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
+		(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
+		return chip->vendor.locality;
+
+	return -EACCES;
+
+} /* check_locality() */
+
+/*
+ * request_locality request the TPM locality
+ * @param: chip, the chip description
+ * @return: the active locality or EACCESS.
+ */
+static int request_locality(struct tpm_chip *chip)
+{
+	unsigned long stop;
+	long rc;
+	struct i2c_client *client;
+	u8 data;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+
+	if (check_locality(chip) == chip->vendor.locality)
+		return chip->vendor.locality;
+
+	data = TPM_ACCESS_REQUEST_USE;
+	rc = I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1);
+	if (rc < 0)
+		goto end;
+
+	if (chip->vendor.irq) {
+		rc = wait_for_serirq_timeout(chip, (check_locality
+						       (chip) >= 0),
+						      chip->vendor.timeout_a);
+		if (rc > 0)
+			return chip->vendor.locality;
+	} else{
+		stop = jiffies + chip->vendor.timeout_a;
+		do {
+			if (check_locality(chip) >= 0)
+				return chip->vendor.locality;
+			msleep(TPM_TIMEOUT);
+		} while (time_before(jiffies, stop));
+	}
+	rc = -EACCES;
+end:
+	return rc;
+} /* request_locality() */
+
+/*
+ * release_locality release the active locality
+ * @param: chip, the tpm chip description.
+ */
+static void release_locality(struct tpm_chip *chip)
+{
+	struct i2c_client *client;
+	u8 data;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+	data = TPM_ACCESS_ACTIVE_LOCALITY;
+
+	I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1);
+}
+
+/*
+ * get_burstcount return the burstcount address 0x19 0x1A
+ * @param: chip, the chip description
+ * return: the burstcount.
+ */
+static int get_burstcount(struct tpm_chip *chip)
+{
+	unsigned long stop;
+	int burstcnt, status;
+	u8 tpm_reg, temp;
+
+	struct i2c_client *client = (struct i2c_client *) chip->vendor.iobase;
+
+	stop = jiffies + chip->vendor.timeout_d;
+	do {
+		tpm_reg = TPM_STS + 1;
+		status = I2C_READ_DATA(client, tpm_reg, &temp, 1);
+		if (status < 0)
+			goto end;
+
+		tpm_reg = tpm_reg + 1;
+		burstcnt = temp;
+		status = I2C_READ_DATA(client, tpm_reg, &temp, 1);
+		if (status < 0)
+			goto end;
+
+		burstcnt |= temp << 8;
+		if (burstcnt)
+			return burstcnt;
+		msleep(TPM_TIMEOUT);
+	} while (time_before(jiffies, stop));
+
+end:
+	return -EBUSY;
+} /* get_burstcount() */
+
+/*
+ * wait_for_stat wait for a TPM_STS value
+ * @param: chip, the tpm chip description
+ * @param: mask, the value mask to wait
+ * @param: timeout, the timeout
+ * @param: queue, the wait queue.
+ * @return: the tpm status, 0 if success, -ETIME if timeout is reached.
+ */
+static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
+			 wait_queue_head_t *queue)
+{
+	unsigned long stop;
+	long rc;
+	u8 status;
+
+	 if (chip->vendor.irq) {
+		rc = wait_for_serirq_timeout(chip, ((tpm_stm_i2c_status
+							(chip) & mask) ==
+						       mask), timeout);
+		if (rc > 0)
+			return 0;
+	} else{
+		stop = jiffies + timeout;
+		do {
+			msleep(TPM_TIMEOUT);
+			status = tpm_stm_i2c_status(chip);
+			if ((status & mask) == mask)
+				return 0;
+		} while (time_before(jiffies, stop));
+	}
+	return -ETIME;
+} /* wait_for_stat() */
+
+/*
+ * recv_data receive data
+ * @param: chip, the tpm chip description
+ * @param: buf, the buffer where the data are received
+ * @param: count, the number of data to receive
+ * @return: the number of bytes read from TPM FIFO.
+ */
+static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	int size = 0, burstcnt, len;
+	struct i2c_client *client;
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+
+	while (size < count &&
+	       wait_for_stat(chip,
+			     TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+			     chip->vendor.timeout_c,
+			     &chip->vendor.read_queue)
+	       == 0) {
+		burstcnt = get_burstcount(chip);
+		len = min_t(int, burstcnt, count - size);
+		I2C_READ_DATA(client, TPM_DATA_FIFO, buf + size, len);
+		size += len;
+	}
+	return size;
+}
+
+/*
+ * tpm_ioserirq_handler the serirq irq handler
+ * @param: irq, the tpm chip description
+ * @param: dev_id, the description of the chip
+ * @return: the status of the handler.
+ */
+static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id)
+{
+	struct tpm_chip *chip = dev_id;
+	struct i2c_client *client;
+	struct st33zp24_platform_data *pin_infos;
+
+	disable_irq_nosync(irq);
+
+	client = (struct i2c_client *) chip->vendor.iobase;
+	pin_infos = client->dev.platform_data;
+
+	complete(&pin_infos->irq_detection);
+	return IRQ_HANDLED;
+} /* tpm_ioserirq_handler() */
+
+
+/*
+ * tpm_stm_i2c_send send TPM commands through the I2C bus.
+ *
+ * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h
+ * @param: buf,	the buffer to send.
+ * @param: count, the number of bytes to send.
+ * @return: In case of success the number of bytes sent.
+ *			In other case, a < 0 value describing the issue.
+ */
+static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
+			    size_t len)
+{
+	u32 ret = 0, ordinal,
+	    status,
+	    burstcnt = 0, i, size;
+	u8 data;
+	struct i2c_client *client;
+	struct st33zp24_platform_data *pin_infos;
+
+	if (chip == NULL)
+		return -EBUSY;
+	if (len < TPM_HEADER_SIZE)
+		return -EBUSY;
+
+	client = (struct i2c_client *)chip->vendor.iobase;
+	pin_infos = client->dev.platform_data;
+
+	ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
+
+	client->flags = 0;
+
+	ret = request_locality(chip);
+	if (ret < 0)
+		return ret;
+
+	status = tpm_stm_i2c_status(chip);
+	if ((status & TPM_STS_COMMAND_READY) == 0) {
+		tpm_stm_i2c_cancel(chip);
+		if (wait_for_stat
+		    (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
+		     &chip->vendor.int_queue) < 0) {
+			ret = -ETIME;
+			goto out_err;
+		}
+	}
+
+	for (i = 0 ; i < len - 1 ;) {
+		burstcnt = get_burstcount(chip);
+		size = min_t(int, len - i - 1, burstcnt);
+		ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf, size);
+		if (ret < 0)
+			goto out_err;
+
+		i += size;
+	}
+
+	status = tpm_stm_i2c_status(chip);
+	if ((status & TPM_STS_DATA_EXPECT) == 0) {
+		ret = -EIO;
+		goto out_err;
+	}
+
+	ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf + len - 1, 1);
+	if (ret < 0)
+		goto out_err;
+
+	status = tpm_stm_i2c_status(chip);
+	if ((status & TPM_STS_DATA_EXPECT) != 0) {
+		ret = -EIO;
+		goto out_err;
+	}
+
+	data = TPM_STS_GO;
+	I2C_WRITE_DATA(client, TPM_STS, &data, 1);
+
+	return len;
+out_err:
+	tpm_stm_i2c_cancel(chip);
+	release_locality(chip);
+	return ret;
+}
+
+/*
+ * tpm_stm_i2c_recv received TPM response through the I2C bus.
+ * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h.
+ * @param: buf,	the buffer to store datas.
+ * @param: count, the number of bytes to send.
+ * @return: In case of success the number of bytes received.
+ *		In other case, a < 0 value describing the issue.
+ */
+static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
+			    size_t count)
+{
+	int size = 0;
+	int expected;
+
+	struct i2c_client *client;
+	struct st33zp24_platform_data *pin_infos;
+
+	client = (struct i2c_client *)chip->vendor.iobase;
+	pin_infos = client->dev.platform_data;
+
+
+	if (chip == NULL)
+		return -EBUSY;
+
+	if (count < TPM_HEADER_SIZE) {
+		size = -EIO;
+		goto out;
+	}
+
+	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;
+	}
+
+out:
+	chip->vendor.cancel(chip);
+	release_locality(chip);
+	return size;
+}
+
+static const struct file_operations tpm_st33_i2c_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.read = tpm_read,
+	.write = tpm_write,
+	.open = tpm_open,
+	.release = tpm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute *stm_tpm_attrs[] = {
+	&dev_attr_pubek.attr,
+	&dev_attr_pcrs.attr,
+	&dev_attr_enabled.attr,
+	&dev_attr_active.attr,
+	&dev_attr_owned.attr,
+	&dev_attr_temp_deactivated.attr,
+	&dev_attr_caps.attr,
+	&dev_attr_cancel.attr, NULL,
+};
+
+static struct attribute_group stm_tpm_attr_grp = {
+	.attrs = stm_tpm_attrs
+};
+
+static struct tpm_vendor_specific st_i2c_tpm = {
+	.send = tpm_stm_i2c_send,
+	.recv = tpm_stm_i2c_recv,
+	.cancel = tpm_stm_i2c_cancel,
+	.status = tpm_stm_i2c_status,
+	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_canceled = TPM_STS_COMMAND_READY,
+	.attr_group = &stm_tpm_attr_grp,
+	.miscdev = {.fops = &tpm_st33_i2c_fops,},
+};
+
+static int interrupts ;
+module_param(interrupts, int, 0444);
+MODULE_PARM_DESC(interrupts, "Enable interrupts");
+
+static int power_mgt = 1;
+module_param(power_mgt, int, 0444);
+MODULE_PARM_DESC(power_mgt, "Power Management");
+
+/*
+ * tpm_st33_i2c_probe initialize the TPM device
+ * @param: client, the i2c_client drescription (TPM I2C description).
+ * @param: id, the i2c_device_id struct.
+ * @return: 0 in case of success.
+ *	 -1 in other case.
+ */
+static int
+tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	u32 err;
+	u8 intmask;
+	struct tpm_chip *chip;
+	struct st33zp24_platform_data *platform_data;
+
+	err = 0;
+
+	if (client == NULL) {
+		dev_info(&client->dev, "client is NULL. exiting.\n");
+		err = -ENODEV;
+		goto end;
+	}
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_info(&client->dev, "client not i2c capable\n");
+		err = -ENODEV;
+		goto end;
+	}
+
+	chip = tpm_register_hardware(&client->dev, &st_i2c_tpm);
+	if (!chip) {
+		dev_info(&client->dev, "fail chip\n");
+		err = -ENODEV;
+		goto end;
+	}
+
+	platform_data = client->dev.platform_data;
+	platform_data->tpm_i2c_buffer[0] =
+	    kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+	if (platform_data->tpm_i2c_buffer[0] == NULL) {
+		err = -ENOMEM;
+		goto _tpm_clean_answer;
+	}
+	platform_data->tpm_i2c_buffer[1] =
+	    kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+	if (platform_data->tpm_i2c_buffer[1] == NULL) {
+		err = -ENOMEM;
+		goto _tpm_clean_response;
+	}
+
+	chip->vendor.iobase = client;
+
+	chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
+	chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+
+	chip->vendor.locality = LOCALITY0;
+
+	if (power_mgt) {
+		err = gpio_request(platform_data->io_lpcpd, "TPM IO_LPCPD");
+		if (err)
+			goto _gpio_init1;
+		gpio_set_value(platform_data->io_lpcpd, 1);
+	}
+
+	if (interrupts) {
+		init_completion(&platform_data->irq_detection);
+		if (request_locality(chip) != LOCALITY0) {
+			err = -ENODEV;
+			goto _tpm_clean_response;
+		}
+		err = gpio_request(platform_data->io_serirq, "TPM IO_SERIRQ");
+		if (err)
+			goto _gpio_init2;
+
+		clear_interruption(client);
+		err = request_irq(gpio_to_irq(platform_data->io_serirq),
+				&tpm_ioserirq_handler,
+				IRQF_TRIGGER_HIGH,
+				"TPM SERIRQ management", chip);
+		if (err < 0) {
+			dev_err(chip->dev , "TPM SERIRQ signals %d not available\n",
+			gpio_to_irq(platform_data->io_serirq));
+			goto _irq_set;
+		}
+
+		err = I2C_READ_DATA(client, TPM_INT_ENABLE, &intmask, 1);
+		if (err < 0)
+			goto _irq_set;
+
+		intmask |= TPM_INTF_CMD_READY_INT
+			|  TPM_INTF_FIFO_AVALAIBLE_INT
+			|  TPM_INTF_WAKE_UP_READY_INT
+			|  TPM_INTF_LOCALITY_CHANGE_INT
+			|  TPM_INTF_STS_VALID_INT
+			|  TPM_INTF_DATA_AVAIL_INT;
+
+		err = I2C_WRITE_DATA(client, TPM_INT_ENABLE, &intmask, 1);
+		if (err < 0)
+			goto _irq_set;
+
+		intmask = TPM_GLOBAL_INT_ENABLE;
+		err = I2C_WRITE_DATA(client, (TPM_INT_ENABLE + 3), &intmask, 1);
+		if (err < 0)
+			goto _irq_set;
+
+		err = I2C_READ_DATA(client, TPM_INT_STATUS, &intmask, 1);
+		if (err < 0)
+			goto _irq_set;
+
+		chip->vendor.irq = interrupts;
+
+		tpm_gen_interrupt(chip);
+	}
+
+	tpm_get_timeouts(chip);
+
+	i2c_set_clientdata(client, chip);
+	platform_data->bChipF = false;
+
+	dev_info(chip->dev, "TPM I2C Initialized\n");
+	return 0;
+_irq_set:
+	free_irq(gpio_to_irq(platform_data->io_serirq), (void *) chip);
+_gpio_init2:
+	if (platform_data && interrupts)
+		gpio_free(platform_data->io_serirq);
+_gpio_init1:
+	if (platform_data && power_mgt)
+		gpio_free(platform_data->io_lpcpd);
+_tpm_clean_response:
+	tpm_remove_hardware(chip->dev);
+	if (platform_data->tpm_i2c_buffer[1] != NULL) {
+		kzfree(platform_data->tpm_i2c_buffer[1]);
+		platform_data->tpm_i2c_buffer[1] = NULL;
+	}
+_tpm_clean_answer:
+	if (platform_data->tpm_i2c_buffer[0] != NULL) {
+		kzfree(platform_data->tpm_i2c_buffer[0]);
+		platform_data->tpm_i2c_buffer[0] = NULL;
+	}
+
+	platform_data->bChipF = true;
+end:
+	pr_info("TPM I2C initialisation fail\n");
+	return err;
+}
+
+/*
+ * tpm_st33_i2c_remove remove the TPM device
+ * @param: client, the i2c_client drescription (TPM I2C description).
+		clear_bit(0, &chip->is_open);
+ * @return: 0 in case of success.
+ */
+static __devexit int tpm_st33_i2c_remove(struct i2c_client *client)
+{
+	struct tpm_chip *chip = (struct tpm_chip *)i2c_get_clientdata(client);
+	struct st33zp24_platform_data *pin_infos =
+		((struct i2c_client *) chip->vendor.iobase)->dev.platform_data;
+
+	if (pin_infos != NULL) {
+		free_irq(pin_infos->io_serirq, chip);
+
+		gpio_free(pin_infos->io_serirq);
+		gpio_free(pin_infos->io_lpcpd);
+
+		if (pin_infos->bChipF != true)
+			tpm_remove_hardware(chip->dev);
+		if (pin_infos->tpm_i2c_buffer[1] != NULL) {
+			kzfree(pin_infos->tpm_i2c_buffer[1]);
+			pin_infos->tpm_i2c_buffer[1] = NULL;
+		}
+		if (pin_infos->tpm_i2c_buffer[0] != NULL) {
+			kzfree(pin_infos->tpm_i2c_buffer[0]);
+			pin_infos->tpm_i2c_buffer[0] = NULL;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * tpm_st33_i2c_pm_suspend suspend the TPM device
+ * Added: Work around when suspend and no tpm application is running, suspend
+ * may fail because chip->data_buffer is not set (only set in tpm_open in Linux
+ * TPM core)
+ * @param: client, the i2c_client drescription (TPM I2C description).
+ * @param: mesg, the power management message.
+ * @return: 0 in case of success.
+ */
+static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	struct tpm_chip *chip =
+	    (struct tpm_chip *)i2c_get_clientdata(client);
+	struct st33zp24_platform_data *pin_infos =
+		((struct i2c_client *)chip->vendor.iobase)->dev.platform_data;
+	int ret = 0;
+
+	if (power_mgt)
+		gpio_set_value(pin_infos->io_lpcpd, 0);
+	else{
+		if (chip->data_buffer == NULL)
+			chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
+		ret = tpm_pm_suspend(&client->dev);
+	}
+	return ret;
+}				/* tpm_st33_i2c_suspend() */
+
+/*
+ * tpm_st33_i2c_pm_resume resume the TPM device
+ * @param: client, the i2c_client drescription (TPM I2C description).
+ * @return: 0 in case of success.
+ */
+static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
+{
+	struct tpm_chip *chip =
+	    (struct tpm_chip *)i2c_get_clientdata(client);
+	struct st33zp24_platform_data *pin_infos =
+		((struct i2c_client *)chip->vendor.iobase)->dev.platform_data;
+
+	int ret = 0;
+
+	if (power_mgt) {
+		gpio_set_value(pin_infos->io_lpcpd, 1);
+		ret = wait_for_serirq_timeout(chip,
+					  (chip->vendor.status(chip) &&
+					  TPM_STS_VALID) == TPM_STS_VALID,
+					  chip->vendor.timeout_b);
+	} else{
+	if (chip->data_buffer == NULL)
+		chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
+	ret = tpm_pm_resume(&client->dev);
+	if (!ret)
+		tpm_do_selftest(chip);
+	}
+	return ret;
+}				/* tpm_st33_i2c_pm_resume() */
+
+static const struct i2c_device_id tpm_st33_i2c_id[] = {
+	{TPM_ST33_I2C, 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, tpm_st33_i2c_id);
+
+static struct i2c_driver tpm_st33_i2c_driver = {
+	.driver = {
+		   .owner = THIS_MODULE,
+		   .name = TPM_ST33_I2C,
+		   },
+	.probe = tpm_st33_i2c_probe,
+	.remove = tpm_st33_i2c_remove,
+	.resume = tpm_st33_i2c_pm_resume,
+	.suspend = tpm_st33_i2c_pm_suspend,
+	.id_table = tpm_st33_i2c_id
+};
+
+/*
+ * tpm_st33_i2c_init initialize driver
+ * @return: 0 if successful, else non zero value.
+ */
+static int __init tpm_st33_i2c_init(void)
+{
+	return i2c_add_driver(&tpm_st33_i2c_driver);
+}
+
+/*
+ * tpm_st33_i2c_exit The kernel calls this function during unloading the
+ * module or during shut down process
+ */
+static void __exit tpm_st33_i2c_exit(void)
+{
+	i2c_del_driver(&tpm_st33_i2c_driver);
+}
+
+module_init(tpm_st33_i2c_init);
+module_exit(tpm_st33_i2c_exit);
+
+MODULE_AUTHOR("Christophe Ricard (tpmsupport@st.com)");
+MODULE_DESCRIPTION("STM TPM I2C ST33 Driver");
+MODULE_VERSION("1.2.0");
diff --git a/drivers/char/tpm/tpm_stm_st33_i2c.h b/drivers/char/tpm/tpm_stm_st33_i2c.h
new file mode 100644
index 0000000..d390542
--- /dev/null
+++ b/drivers/char/tpm/tpm_stm_st33_i2c.h
@@ -0,0 +1,81 @@
+/*
+ * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
+ * Copyright (C) 2009, 2010  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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * STMicroelectronics version 1.2.0, Copyright (C) 2010
+ * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
+ * This is free software, and you are welcome to redistribute it
+ * under certain conditions.
+ *
+ * @Author: Christophe RICARD tpmsupport@st.com
+ *
+ * @File: stm_st33_tpm_i2c.h
+ *
+ * @Date: 09/15/2010
+ */
+#ifndef __STM_ST33_TPM_I2C_MAIN_H__
+#define __STM_ST33_TPM_I2C_MAIN_H__
+
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/sysfs.h>
+#include <linux/gpio.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+#include "tpm.h"
+
+#define MINOR_NUM_I2C		224
+
+#define TPM_ACCESS			(0x0)
+#define TPM_STS				(0x18)
+#define TPM_HASH_END			(0x20)
+#define TPM_DATA_FIFO			(0x24)
+#define TPM_HASH_DATA			(0x24)
+#define TPM_HASH_START			(0x28)
+#define TPM_INTF_CAPABILITY		(0x14)
+#define TPM_INT_STATUS			(0x10)
+#define TPM_INT_ENABLE			(0x08)
+
+#define TPM_DUMMY_BYTE			0xAA
+#define TPM_WRITE_DIRECTION		0x80
+#define TPM_HEADER_SIZE			10
+#define TPM_BUFSIZE			2048
+
+#define LOCALITY0		0
+
+struct st_tpm_hash {
+	int size;
+	u8 *data;
+};
+
+#endif /* __STM_ST33_TPM_I2C_MAIN_H__ */
diff --git a/include/linux/i2c/tpm_stm_st33_i2c.h b/include/linux/i2c/tpm_stm_st33_i2c.h
new file mode 100644
index 0000000..e3ce42d
--- /dev/null
+++ b/include/linux/i2c/tpm_stm_st33_i2c.h
@@ -0,0 +1,47 @@
+/*
+* STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
+* Copyright (C) 2009, 2010 STMicroelectronics
+* Christophe RICARD tpmsupport@st.com
+* 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, write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* STMicroelectronics version 1.2.0, Copyright (C) 2010
+* STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
+* This is free software, and you are welcome to redistribute it
+* under certain conditions.
+*
+* @File: stm_st33_tpm_i2c.h
+*
+* @Date: 06/15/2008
+*/
+#ifndef __STM_ST33_TPM_I2C_H__
+#define __STM_ST33_TPM_I2C_H__
+
+#include <linux/i2c.h>
+
+#define TPM_ST33_I2C			"st33zp24_i2c"
+#define TPM_I2C_ST33_ADDR_WR_LOC0	(0x26 >> 1)
+
+
+struct st33zp24_platform_data {
+	int io_serirq;
+	int io_lpcpd;
+	struct i2c_client *client;
+	bool bChipF;
+	u8 *tpm_i2c_buffer[2]; /* 0 Request 1 Response */
+	struct completion irq_detection;
+	struct mutex lock;
+};
+
+#endif /* __STM_ST33_TPM_I2C_H__ */
-- 
1.7.9.5


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

* Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-11-28 17:48           ` Mathias LEBLANC
@ 2012-11-28 19:04             ` Kent Yoder
  2012-11-29  0:04             ` Peter Hüwe
  1 sibling, 0 replies; 33+ messages in thread
From: Kent Yoder @ 2012-11-28 19:04 UTC (permalink / raw)
  To: Mathias LEBLANC
  Cc: Kent Yoder, Jean-Luc BLANC, linux-kernel, Rajiv Andrade,
	tpmdd-devel, Sirrix AG

On Wed, Nov 28, 2012 at 06:48:57PM +0100, Mathias LEBLANC wrote:
> Ok, so i have patch the ST33 I2C driver on this branch and correct some errors.
> I send you the patch for the kernel 3.x 
> I have no error on compilation, tell me if you have problems.
> I have implemented the tpm_do_selftest function to get the tpm ready, but it can be removed

 This looks like its base64 encoded...

> ________________________________________
> From: Kent Yoder [shpedoikal@gmail.com]
> Sent: 28 November 2012 16:31
> To: Mathias LEBLANC
> Cc: Kent Yoder; Jean-Luc BLANC; linux-kernel@vger.kernel.org; Rajiv Andrade; tpmdd-devel@lists.sourceforge.net; Sirrix AG
> Subject: Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
> 
> On Wed, Nov 28, 2012 at 2:54 AM, Mathias LEBLANC <Mathias.LEBLANC@st.com> wrote:
> > Hi Kent,
> >
> > I have been tried the patch on your linux branch and indeed, i have an error about tpm_continue_seftest.
> > What is the kernel I should use to test officially my patch? Because i saw a lot of different version of linux kernel with the tpm_continue_seftest function.
> > I used this repo git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 for my tests.
> 
>   The tree url I sent you is the correct one. Make sure you use the
> "next" branch.
> 
> Kent
> 
> > Matthias Leblanc
> >
> > ________________________________________From: Kent Yoder [shpedoikal@gmail.com]
> > Sent: 27 November 2012 15:48
> > To: Mathias LEBLANC
> > Cc: Kent Yoder; Jean-Luc BLANC; linux-kernel@vger.kernel.org; Rajiv Andrade; tpmdd-devel@lists.sourceforge.net; Sirrix AG
> > Subject: Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
> >
> > On Tue, Nov 27, 2012 at 2:44 AM, Mathias LEBLANC <Mathias.LEBLANC@st.com> wrote:
> >> Hi Kent,
> >>
> >> What's version of the kernel do you compiled?
> >> I don't understand why you have some problem with formating, i have send you the patch with no error and warning of code formating.
> >> The tpm_continue_selftest_nocheck()  (in kernel 3.x.x) and tpm_continue_selftest() (in kernel 2.6.x) is called to have the tpm ready.
> >> If the tpm_continue_selftest is not called by the driver, it will be use in the applications.
> >
> > Apply against this tree's "next" branch.
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git
> >
> > Thanks,
> > Kent
> >
> >> Regards,
> >>
> >> Matthias Leblanc
> >> ________________________________________
> >> From: Kent Yoder [key@linux.vnet.ibm.com]
> >> Sent: 26 November 2012 18:46
> >> To: Mathias LEBLANC
> >> Cc: Rajiv Andrade; Marcel Selhorst; Sirrix AG; tpmdd-devel@lists.sourceforge.net; Debora Velarde; linux-kernel@vger.kernel.org; Jean-Luc BLANC
> >> Subject: Re: [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
> >>
> >> Hi Mathias,
> >>
> >> On Mon, Nov 19, 2012 at 11:15:21PM +0100, Mathias Leblanc wrote:
> >>>  * STMicroelectronics version 1.2.0, Copyright (C) 2010
> >>>  * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
> >>>  * This is free software, and you are welcome to redistribute it
> >>>  * under certain conditions.
> >>
> >>> This is the driver for TPM chip from ST Microelectronics.
> >>>
> >>> If you have a TPM security chip from STMicroelectronics working with
> >>> an I2C, in menuconfig or .config choose the tpm driver on
> >>> device --> tpm and activate the protocol of your choice before compiling
> >>> the kernel.
> >>> The driver will be accessible from within Linux.
> >>>
> >>> Tested on linux x86/x64, beagleboard REV B & XM REV C and CHROMIUM OS
> >>> on kernel 3.x.x
> >>>
> >>> Signed-off-by: Mathias Leblanc <mathias.leblanc@st.com>
> >>> ---
> >>>  drivers/char/tpm/tpm_stm_st33_i2c.c  |  903 ++++++++++++++++++++++++++++++++++
> >>>  drivers/char/tpm/tpm_stm_st33_i2c.h  |   81 +++
> >>>  include/linux/i2c/tpm_stm_st33_i2c.h |   47 ++
> >>>  3 files changed, 1031 insertions(+)
> >>>  create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.c
> >>>  create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.h
> >>>  create mode 100644 include/linux/i2c/tpm_stm_st33_i2c.h
> >>
> >>   I'm still getting the compiler errors I mentioned earlier. I've fixed
> >> them up with the patch below (plus some formatting), all except for the
> >> tpm_continue_selftest_nocheck() problem. Do you really need to call
> >> continue selftest on resume?  That strikes me as out of place here.
> >> What's making the call to the TPM to start the self test in that case?
> >>
> >> Please test with the patch below.
> >>
> >> Thanks,
> >> Kent
> >>
> >>
> >> diff --git a/drivers/char/tpm/tpm_stm_st33_i2c.c b/drivers/char/tpm/tpm_stm_st33_i2c.c
> >> index 52f3380..67f81b6 100644
> >> --- a/drivers/char/tpm/tpm_stm_st33_i2c.c
> >> +++ b/drivers/char/tpm/tpm_stm_st33_i2c.c
> >> @@ -722,7 +722,7 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
> >>                         goto _irq_set;
> >>
> >>                 intmask = TPM_GLOBAL_INT_ENABLE;
> >> -               err = I2C_WRITE_DATA(client, TPM_INT_ENABLE + 3, &intmask, 1);
> >> +               err = I2C_WRITE_DATA(client, (TPM_INT_ENABLE + 3), &intmask, 1);
> >>                 if (err < 0)
> >>                         goto _irq_set;
> >>
> >> @@ -820,10 +820,10 @@ static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
> >>
> >>         if (power_mgt)
> >>                 gpio_set_value(pin_infos->io_lpcpd, 0);
> >> -       else{
> >> +       else {
> >>                 if (chip->data_buffer == NULL)
> >>                         chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
> >> -               ret = tpm_pm_suspend(&client->dev, mesg);
> >> +               ret = tpm_pm_suspend(&client->dev);
> >>         }
> >>         return ret;
> >>  }                              /* tpm_st33_i2c_suspend() */
> >> @@ -848,12 +848,12 @@ static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
> >>                                           (chip->vendor.status(chip) &&
> >>                                           TPM_STS_VALID) == TPM_STS_VALID,
> >>                                           chip->vendor.timeout_b);
> >> -       } else{
> >> -       if (chip->data_buffer == NULL)
> >> -               chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
> >> -       ret = tpm_pm_resume(&client->dev);
> >> -       if (!ret)
> >> -               tpm_continue_selftest_nocheck(chip);
> >> +       } else {
> >> +               if (chip->data_buffer == NULL)
> >> +                       chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
> >> +               ret = tpm_pm_resume(&client->dev);
> >> +               if (!ret)
> >> +                       tpm_continue_selftest_nocheck(chip);
> >>         }
> >>         return ret;
> >>  }                              /* tpm_st33_i2c_pm_resume() */
> >>
> >> ------------------------------------------------------------------------------
> >> Monitor your physical, virtual and cloud infrastructure from a single
> >> web console. Get in-depth insight into apps, servers, databases, vmware,
> >> SAP, cloud infrastructure, etc. Download 30-day Free Trial.
> >> Pricing starts from $795 for 25 servers or applications!
> >> http://p.sf.net/sfu/zoho_dev2dev_nov
> >> _______________________________________________
> >> tpmdd-devel mailing list
> >> tpmdd-devel@lists.sourceforge.net
> >> https://lists.sourceforge.net/lists/listinfo/tpmdd-devel
> >
> >
> >
> > --
> > IBM LTC Security
> 
> 
> 
> --
> IBM LTC Security

> From 3cf4687665a0bcffe89de92416f0d5886a90100f Mon Sep 17 00:00:00 2001
> From: Mathias Leblanc <mathias.leblanc@st.com>
> Date: Wed, 28 Nov 2012 18:22:24 +0100
> Subject: [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x
> 
>  * STMicroelectronics version 1.2.0, Copyright (C) 2010
>  * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
>  * This is free software, and you are welcome to redistribute it
>  * under certain conditions.
> 
> This is the driver for TPM chip from ST Microelectronics.
> 
> If you have a TPM security chip from STMicroelectronics working with
> an I2C, in menuconfig or .config choose the tpm driver on
> device --> tpm and activate the protocol of your choice before compiling
> the kernel.
> The driver will be accessible from within Linux.
> 
> Tested on linux x86/x64 on kernel 3.x
> 
> Signed-off-by: Mathias Leblanc <mathias.leblanc@st.com>
> ---
>  drivers/char/tpm/tpm_stm_st33_i2c.c  |  903 ++++++++++++++++++++++++++++++++++
>  drivers/char/tpm/tpm_stm_st33_i2c.h  |   81 +++
>  include/linux/i2c/tpm_stm_st33_i2c.h |   47 ++
>  3 files changed, 1031 insertions(+)
>  create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.c
>  create mode 100644 drivers/char/tpm/tpm_stm_st33_i2c.h
>  create mode 100644 include/linux/i2c/tpm_stm_st33_i2c.h
> 
> diff --git a/drivers/char/tpm/tpm_stm_st33_i2c.c b/drivers/char/tpm/tpm_stm_st33_i2c.c
> new file mode 100644
> index 0000000..32cdd5e
> --- /dev/null
> +++ b/drivers/char/tpm/tpm_stm_st33_i2c.c
> @@ -0,0 +1,903 @@
> +/*
> + * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
> + * Copyright (C) 2009, 2010  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, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + *
> + * STMicroelectronics version 1.2.0, Copyright (C) 2010
> + * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
> + * This is free software, and you are welcome to redistribute it
> + * under certain conditions.
> + *
> + * @Author: Christophe RICARD tpmsupport@st.com
> + *
> + * @File: tpm_stm_st33_i2c.c
> + *
> + * @Synopsis:
> + *	09/15/2010:	First shot driver tpm_tis driver for
> +			 lpc is used as model.
> + */
> +
> +#include <linux/i2c/tpm_stm_st33_i2c.h>
> +
> +#include "tpm_stm_st33_i2c.h"
> +
> +enum stm33zp24_access {
> +	TPM_ACCESS_VALID = 0x80,
> +	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
> +	TPM_ACCESS_REQUEST_PENDING = 0x04,
> +	TPM_ACCESS_REQUEST_USE = 0x02,
> +};
> +
> +enum stm33zp24_status {
> +	TPM_STS_VALID = 0x80,
> +	TPM_STS_COMMAND_READY = 0x40,
> +	TPM_STS_GO = 0x20,
> +	TPM_STS_DATA_AVAIL = 0x10,
> +	TPM_STS_DATA_EXPECT = 0x08,
> +};
> +
> +enum stm33zp24_int_flags {
> +	TPM_GLOBAL_INT_ENABLE = 0x80,
> +	TPM_INTF_CMD_READY_INT = 0x080,
> +	TPM_INTF_FIFO_AVALAIBLE_INT = 0x040,
> +	TPM_INTF_WAKE_UP_READY_INT = 0x020,
> +	TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
> +	TPM_INTF_STS_VALID_INT = 0x002,
> +	TPM_INTF_DATA_AVAIL_INT = 0x001,
> +};
> +
> +enum tis_defaults {
> +	TIS_SHORT_TIMEOUT = 750,
> +	TIS_LONG_TIMEOUT = 2000,
> +};
> +
> +/*
> + * write8_reg
> + * Send byte to the TIS register according to the ST33ZP24 I2C protocol.
> + * @param: tpm_register, the tpm tis register where the data should be written
> + * @param: tpm_data, the tpm_data to write inside the tpm_register
> + * @param: tpm_size, The length of the data
> + * @return: Returns negative errno, or else the number of bytes written.
> + */
> +static int write8_reg(struct i2c_client *client, u8 tpm_register,
> +		      u8 *tpm_data, u16 tpm_size)
> +{
> +	u8 data;
> +	int value = 0;
> +	struct st33zp24_platform_data *pin_infos;
> +
> +	pin_infos = client->dev.platform_data;
> +
> +	data = tpm_register;
> +	memcpy(pin_infos->tpm_i2c_buffer[0], &data, sizeof(data));
> +	memcpy(pin_infos->tpm_i2c_buffer[0] + 1, tpm_data, tpm_size);
> +	value = i2c_master_send(client, pin_infos->tpm_i2c_buffer[0],
> +				tpm_size + 1);
> +	return value;
> +} /* write8_reg() */
> +
> +/*
> + * read8_reg
> + * Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
> + * @param: tpm_register, the tpm tis register where the data should be read
> + * @param: tpm_data, the TPM response
> + * @param: tpm_size, tpm TPM response size to read.
> + * @return: number of byte read successfully: should be one if success.
> + */
> +static int read8_reg(struct i2c_client *client, u8 tpm_register,
> +		    u8 *tpm_data, int tpm_size)
> +{
> +	u8 status = 0;
> +	u8 data;
> +	struct st33zp24_platform_data *pin_infos;
> +
> +	pin_infos = client->dev.platform_data;
> +
> +	data = TPM_DUMMY_BYTE;
> +	status = write8_reg(client, tpm_register, &data, 1);
> +	if (status == 2)
> +		status = i2c_master_recv(client, tpm_data, tpm_size);
> +	return status;
> +} /* read8_reg() */
> +
> +/*
> + * I2C_WRITE_DATA
> + * Send byte to the TIS register according to the ST33ZP24 I2C protocol.
> + * @param: client, the chip description
> + * @param: tpm_register, the tpm tis register where the data should be written
> + * @param: tpm_data, the tpm_data to write inside the tpm_register
> + * @param: tpm_size, The length of the data
> + * @return: number of byte written successfully: should be one if success.
> + */
> +#define I2C_WRITE_DATA(client, tpm_register, tpm_data, tpm_size) \
> +	(write8_reg(client, tpm_register | \
> +	TPM_WRITE_DIRECTION, tpm_data, tpm_size))
> +
> +/*
> + * I2C_READ_DATA
> + * Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
> + * @param: tpm, the chip description
> + * @param: tpm_register, the tpm tis register where the data should be read
> + * @param: tpm_data, the TPM response
> + * @param: tpm_size, tpm TPM response size to read.
> + * @return: number of byte read successfully: should be one if success.
> + */
> +#define I2C_READ_DATA(client, tpm_register, tpm_data, tpm_size) \
> +	(read8_reg(client, tpm_register, tpm_data, tpm_size))
> +
> +/*
> + * clear_interruption
> + * clear the TPM interrupt register.
> + * @param: tpm, the chip description
> + */
> +static void clear_interruption(struct i2c_client *client)
> +{
> +	u8 interrupt;
> +	I2C_READ_DATA(client, TPM_INT_STATUS, &interrupt, 1);
> +	I2C_WRITE_DATA(client, TPM_INT_STATUS, &interrupt, 1);
> +	I2C_READ_DATA(client, TPM_INT_STATUS, &interrupt, 1);
> +} /* clear_interruption() */
> +
> +/*
> + * _wait_for_interrupt_serirq_timeout
> + * @param: tpm, the chip description
> + * @param: timeout, the timeout of the interrupt
> + * @return: the status of the interruption.
> + */
> +static long _wait_for_interrupt_serirq_timeout(struct tpm_chip *chip,
> +						unsigned long timeout)
> +{
> +	long status;
> +	struct i2c_client *client;
> +	struct st33zp24_platform_data *pin_infos;
> +
> +	client = (struct i2c_client *) chip->vendor.iobase;
> +	pin_infos = client->dev.platform_data;
> +
> +	status = wait_for_completion_interruptible_timeout(
> +					&pin_infos->irq_detection,
> +						timeout);
> +	if (status > 0)
> +		enable_irq(gpio_to_irq(pin_infos->io_serirq));
> +	gpio_direction_input(pin_infos->io_serirq);
> +
> +	return status;
> +} /* wait_for_interrupt_serirq_timeout() */
> +
> +int wait_for_serirq_timeout(struct tpm_chip *chip, bool condition,
> +				 unsigned long timeout)
> +{
> +	int status = 2;
> +	struct i2c_client *client;
> +	struct st33zp24_platform_data *pin_infos;
> +
> +	client = (struct i2c_client *) chip->vendor.iobase;
> +	pin_infos = client->dev.platform_data;
> +
> +	status = _wait_for_interrupt_serirq_timeout(chip, timeout);
> +	if (!status) {
> +		status = -EBUSY;
> +	} else{
> +		clear_interruption(client);
> +		if (condition)
> +			status = 1;
> +	}
> +	return status;
> +}
> +
> +/*
> + * tpm_stm_i2c_cancel, cancel is not implemented.
> + * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h
> + */
> +static void tpm_stm_i2c_cancel(struct tpm_chip *chip)
> +{
> +	struct i2c_client *client;
> +	u8 data;
> +
> +	client = (struct i2c_client *) chip->vendor.iobase;
> +
> +	data = TPM_STS_COMMAND_READY;
> +	I2C_WRITE_DATA(client, TPM_STS, &data, 1);
> +	if (chip->vendor.irq)
> +		wait_for_serirq_timeout(chip, 1, chip->vendor.timeout_a);
> +}	/* tpm_stm_i2c_cancel() */
> +
> +/*
> + * tpm_stm_spi_status return the TPM_STS register
> + * @param: chip, the tpm chip description
> + * @return: the TPM_STS register value.
> + */
> +static u8 tpm_stm_i2c_status(struct tpm_chip *chip)
> +{
> +	struct i2c_client *client;
> +	u8 data;
> +	client = (struct i2c_client *) chip->vendor.iobase;
> +
> +	I2C_READ_DATA(client, TPM_STS, &data, 1);
> +	return data;
> +}				/* tpm_stm_i2c_status() */
> +
> +
> +/*
> + * check_locality if the locality is active
> + * @param: chip, the tpm chip description
> + * @return: the active locality or -EACCESS.
> + */
> +static int check_locality(struct tpm_chip *chip)
> +{
> +	struct i2c_client *client;
> +	u8 data;
> +	u8 status;
> +
> +	client = (struct i2c_client *) chip->vendor.iobase;
> +
> +	status = I2C_READ_DATA(client, TPM_ACCESS, &data, 1);
> +	if (status && (data &
> +		(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
> +		(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
> +		return chip->vendor.locality;
> +
> +	return -EACCES;
> +
> +} /* check_locality() */
> +
> +/*
> + * request_locality request the TPM locality
> + * @param: chip, the chip description
> + * @return: the active locality or EACCESS.
> + */
> +static int request_locality(struct tpm_chip *chip)
> +{
> +	unsigned long stop;
> +	long rc;
> +	struct i2c_client *client;
> +	u8 data;
> +
> +	client = (struct i2c_client *) chip->vendor.iobase;
> +
> +	if (check_locality(chip) == chip->vendor.locality)
> +		return chip->vendor.locality;
> +
> +	data = TPM_ACCESS_REQUEST_USE;
> +	rc = I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1);
> +	if (rc < 0)
> +		goto end;
> +
> +	if (chip->vendor.irq) {
> +		rc = wait_for_serirq_timeout(chip, (check_locality
> +						       (chip) >= 0),
> +						      chip->vendor.timeout_a);
> +		if (rc > 0)
> +			return chip->vendor.locality;
> +	} else{
> +		stop = jiffies + chip->vendor.timeout_a;
> +		do {
> +			if (check_locality(chip) >= 0)
> +				return chip->vendor.locality;
> +			msleep(TPM_TIMEOUT);
> +		} while (time_before(jiffies, stop));
> +	}
> +	rc = -EACCES;
> +end:
> +	return rc;
> +} /* request_locality() */
> +
> +/*
> + * release_locality release the active locality
> + * @param: chip, the tpm chip description.
> + */
> +static void release_locality(struct tpm_chip *chip)
> +{
> +	struct i2c_client *client;
> +	u8 data;
> +
> +	client = (struct i2c_client *) chip->vendor.iobase;
> +	data = TPM_ACCESS_ACTIVE_LOCALITY;
> +
> +	I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1);
> +}
> +
> +/*
> + * get_burstcount return the burstcount address 0x19 0x1A
> + * @param: chip, the chip description
> + * return: the burstcount.
> + */
> +static int get_burstcount(struct tpm_chip *chip)
> +{
> +	unsigned long stop;
> +	int burstcnt, status;
> +	u8 tpm_reg, temp;
> +
> +	struct i2c_client *client = (struct i2c_client *) chip->vendor.iobase;
> +
> +	stop = jiffies + chip->vendor.timeout_d;
> +	do {
> +		tpm_reg = TPM_STS + 1;
> +		status = I2C_READ_DATA(client, tpm_reg, &temp, 1);
> +		if (status < 0)
> +			goto end;
> +
> +		tpm_reg = tpm_reg + 1;
> +		burstcnt = temp;
> +		status = I2C_READ_DATA(client, tpm_reg, &temp, 1);
> +		if (status < 0)
> +			goto end;
> +
> +		burstcnt |= temp << 8;
> +		if (burstcnt)
> +			return burstcnt;
> +		msleep(TPM_TIMEOUT);
> +	} while (time_before(jiffies, stop));
> +
> +end:
> +	return -EBUSY;
> +} /* get_burstcount() */
> +
> +/*
> + * wait_for_stat wait for a TPM_STS value
> + * @param: chip, the tpm chip description
> + * @param: mask, the value mask to wait
> + * @param: timeout, the timeout
> + * @param: queue, the wait queue.
> + * @return: the tpm status, 0 if success, -ETIME if timeout is reached.
> + */
> +static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
> +			 wait_queue_head_t *queue)
> +{
> +	unsigned long stop;
> +	long rc;
> +	u8 status;
> +
> +	 if (chip->vendor.irq) {
> +		rc = wait_for_serirq_timeout(chip, ((tpm_stm_i2c_status
> +							(chip) & mask) ==
> +						       mask), timeout);
> +		if (rc > 0)
> +			return 0;
> +	} else{
> +		stop = jiffies + timeout;
> +		do {
> +			msleep(TPM_TIMEOUT);
> +			status = tpm_stm_i2c_status(chip);
> +			if ((status & mask) == mask)
> +				return 0;
> +		} while (time_before(jiffies, stop));
> +	}
> +	return -ETIME;
> +} /* wait_for_stat() */
> +
> +/*
> + * recv_data receive data
> + * @param: chip, the tpm chip description
> + * @param: buf, the buffer where the data are received
> + * @param: count, the number of data to receive
> + * @return: the number of bytes read from TPM FIFO.
> + */
> +static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
> +{
> +	int size = 0, burstcnt, len;
> +	struct i2c_client *client;
> +
> +	client = (struct i2c_client *) chip->vendor.iobase;
> +
> +	while (size < count &&
> +	       wait_for_stat(chip,
> +			     TPM_STS_DATA_AVAIL | TPM_STS_VALID,
> +			     chip->vendor.timeout_c,
> +			     &chip->vendor.read_queue)
> +	       == 0) {
> +		burstcnt = get_burstcount(chip);
> +		len = min_t(int, burstcnt, count - size);
> +		I2C_READ_DATA(client, TPM_DATA_FIFO, buf + size, len);
> +		size += len;
> +	}
> +	return size;
> +}
> +
> +/*
> + * tpm_ioserirq_handler the serirq irq handler
> + * @param: irq, the tpm chip description
> + * @param: dev_id, the description of the chip
> + * @return: the status of the handler.
> + */
> +static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id)
> +{
> +	struct tpm_chip *chip = dev_id;
> +	struct i2c_client *client;
> +	struct st33zp24_platform_data *pin_infos;
> +
> +	disable_irq_nosync(irq);
> +
> +	client = (struct i2c_client *) chip->vendor.iobase;
> +	pin_infos = client->dev.platform_data;
> +
> +	complete(&pin_infos->irq_detection);
> +	return IRQ_HANDLED;
> +} /* tpm_ioserirq_handler() */
> +
> +
> +/*
> + * tpm_stm_i2c_send send TPM commands through the I2C bus.
> + *
> + * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h
> + * @param: buf,	the buffer to send.
> + * @param: count, the number of bytes to send.
> + * @return: In case of success the number of bytes sent.
> + *			In other case, a < 0 value describing the issue.
> + */
> +static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
> +			    size_t len)
> +{
> +	u32 ret = 0, ordinal,
> +	    status,
> +	    burstcnt = 0, i, size;
> +	u8 data;
> +	struct i2c_client *client;
> +	struct st33zp24_platform_data *pin_infos;
> +
> +	if (chip == NULL)
> +		return -EBUSY;
> +	if (len < TPM_HEADER_SIZE)
> +		return -EBUSY;
> +
> +	client = (struct i2c_client *)chip->vendor.iobase;
> +	pin_infos = client->dev.platform_data;
> +
> +	ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
> +
> +	client->flags = 0;
> +
> +	ret = request_locality(chip);
> +	if (ret < 0)
> +		return ret;
> +
> +	status = tpm_stm_i2c_status(chip);
> +	if ((status & TPM_STS_COMMAND_READY) == 0) {
> +		tpm_stm_i2c_cancel(chip);
> +		if (wait_for_stat
> +		    (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
> +		     &chip->vendor.int_queue) < 0) {
> +			ret = -ETIME;
> +			goto out_err;
> +		}
> +	}
> +
> +	for (i = 0 ; i < len - 1 ;) {
> +		burstcnt = get_burstcount(chip);
> +		size = min_t(int, len - i - 1, burstcnt);
> +		ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf, size);
> +		if (ret < 0)
> +			goto out_err;
> +
> +		i += size;
> +	}
> +
> +	status = tpm_stm_i2c_status(chip);
> +	if ((status & TPM_STS_DATA_EXPECT) == 0) {
> +		ret = -EIO;
> +		goto out_err;
> +	}
> +
> +	ret = I2C_WRITE_DATA(client, TPM_DATA_FIFO, buf + len - 1, 1);
> +	if (ret < 0)
> +		goto out_err;
> +
> +	status = tpm_stm_i2c_status(chip);
> +	if ((status & TPM_STS_DATA_EXPECT) != 0) {
> +		ret = -EIO;
> +		goto out_err;
> +	}
> +
> +	data = TPM_STS_GO;
> +	I2C_WRITE_DATA(client, TPM_STS, &data, 1);
> +
> +	return len;
> +out_err:
> +	tpm_stm_i2c_cancel(chip);
> +	release_locality(chip);
> +	return ret;
> +}
> +
> +/*
> + * tpm_stm_i2c_recv received TPM response through the I2C bus.
> + * @param: chip, the tpm_chip description as specified in driver/char/tpm/tpm.h.
> + * @param: buf,	the buffer to store datas.
> + * @param: count, the number of bytes to send.
> + * @return: In case of success the number of bytes received.
> + *		In other case, a < 0 value describing the issue.
> + */
> +static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf,
> +			    size_t count)
> +{
> +	int size = 0;
> +	int expected;
> +
> +	struct i2c_client *client;
> +	struct st33zp24_platform_data *pin_infos;
> +
> +	client = (struct i2c_client *)chip->vendor.iobase;
> +	pin_infos = client->dev.platform_data;
> +
> +
> +	if (chip == NULL)
> +		return -EBUSY;
> +
> +	if (count < TPM_HEADER_SIZE) {
> +		size = -EIO;
> +		goto out;
> +	}
> +
> +	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;
> +	}
> +
> +out:
> +	chip->vendor.cancel(chip);
> +	release_locality(chip);
> +	return size;
> +}
> +
> +static const struct file_operations tpm_st33_i2c_fops = {
> +	.owner = THIS_MODULE,
> +	.llseek = no_llseek,
> +	.read = tpm_read,
> +	.write = tpm_write,
> +	.open = tpm_open,
> +	.release = tpm_release,
> +};
> +
> +static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
> +static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
> +static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
> +static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
> +static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
> +static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL);
> +static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
> +static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
> +
> +static struct attribute *stm_tpm_attrs[] = {
> +	&dev_attr_pubek.attr,
> +	&dev_attr_pcrs.attr,
> +	&dev_attr_enabled.attr,
> +	&dev_attr_active.attr,
> +	&dev_attr_owned.attr,
> +	&dev_attr_temp_deactivated.attr,
> +	&dev_attr_caps.attr,
> +	&dev_attr_cancel.attr, NULL,
> +};
> +
> +static struct attribute_group stm_tpm_attr_grp = {
> +	.attrs = stm_tpm_attrs
> +};
> +
> +static struct tpm_vendor_specific st_i2c_tpm = {
> +	.send = tpm_stm_i2c_send,
> +	.recv = tpm_stm_i2c_recv,
> +	.cancel = tpm_stm_i2c_cancel,
> +	.status = tpm_stm_i2c_status,
> +	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
> +	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
> +	.req_canceled = TPM_STS_COMMAND_READY,
> +	.attr_group = &stm_tpm_attr_grp,
> +	.miscdev = {.fops = &tpm_st33_i2c_fops,},
> +};
> +
> +static int interrupts ;
> +module_param(interrupts, int, 0444);
> +MODULE_PARM_DESC(interrupts, "Enable interrupts");
> +
> +static int power_mgt = 1;
> +module_param(power_mgt, int, 0444);
> +MODULE_PARM_DESC(power_mgt, "Power Management");
> +
> +/*
> + * tpm_st33_i2c_probe initialize the TPM device
> + * @param: client, the i2c_client drescription (TPM I2C description).
> + * @param: id, the i2c_device_id struct.
> + * @return: 0 in case of success.
> + *	 -1 in other case.
> + */
> +static int
> +tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
> +{
> +	u32 err;
> +	u8 intmask;
> +	struct tpm_chip *chip;
> +	struct st33zp24_platform_data *platform_data;
> +
> +	err = 0;
> +
> +	if (client == NULL) {
> +		dev_info(&client->dev, "client is NULL. exiting.\n");
> +		err = -ENODEV;
> +		goto end;
> +	}
> +
> +	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
> +		dev_info(&client->dev, "client not i2c capable\n");
> +		err = -ENODEV;
> +		goto end;
> +	}
> +
> +	chip = tpm_register_hardware(&client->dev, &st_i2c_tpm);
> +	if (!chip) {
> +		dev_info(&client->dev, "fail chip\n");
> +		err = -ENODEV;
> +		goto end;
> +	}
> +
> +	platform_data = client->dev.platform_data;
> +	platform_data->tpm_i2c_buffer[0] =
> +	    kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
> +	if (platform_data->tpm_i2c_buffer[0] == NULL) {
> +		err = -ENOMEM;
> +		goto _tpm_clean_answer;
> +	}
> +	platform_data->tpm_i2c_buffer[1] =
> +	    kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
> +	if (platform_data->tpm_i2c_buffer[1] == NULL) {
> +		err = -ENOMEM;
> +		goto _tpm_clean_response;
> +	}
> +
> +	chip->vendor.iobase = client;
> +
> +	chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> +	chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
> +	chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> +	chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
> +
> +	chip->vendor.locality = LOCALITY0;
> +
> +	if (power_mgt) {
> +		err = gpio_request(platform_data->io_lpcpd, "TPM IO_LPCPD");
> +		if (err)
> +			goto _gpio_init1;
> +		gpio_set_value(platform_data->io_lpcpd, 1);
> +	}
> +
> +	if (interrupts) {
> +		init_completion(&platform_data->irq_detection);
> +		if (request_locality(chip) != LOCALITY0) {
> +			err = -ENODEV;
> +			goto _tpm_clean_response;
> +		}
> +		err = gpio_request(platform_data->io_serirq, "TPM IO_SERIRQ");
> +		if (err)
> +			goto _gpio_init2;
> +
> +		clear_interruption(client);
> +		err = request_irq(gpio_to_irq(platform_data->io_serirq),
> +				&tpm_ioserirq_handler,
> +				IRQF_TRIGGER_HIGH,
> +				"TPM SERIRQ management", chip);
> +		if (err < 0) {
> +			dev_err(chip->dev , "TPM SERIRQ signals %d not available\n",
> +			gpio_to_irq(platform_data->io_serirq));
> +			goto _irq_set;
> +		}
> +
> +		err = I2C_READ_DATA(client, TPM_INT_ENABLE, &intmask, 1);
> +		if (err < 0)
> +			goto _irq_set;
> +
> +		intmask |= TPM_INTF_CMD_READY_INT
> +			|  TPM_INTF_FIFO_AVALAIBLE_INT
> +			|  TPM_INTF_WAKE_UP_READY_INT
> +			|  TPM_INTF_LOCALITY_CHANGE_INT
> +			|  TPM_INTF_STS_VALID_INT
> +			|  TPM_INTF_DATA_AVAIL_INT;
> +
> +		err = I2C_WRITE_DATA(client, TPM_INT_ENABLE, &intmask, 1);
> +		if (err < 0)
> +			goto _irq_set;
> +
> +		intmask = TPM_GLOBAL_INT_ENABLE;
> +		err = I2C_WRITE_DATA(client, (TPM_INT_ENABLE + 3), &intmask, 1);
> +		if (err < 0)
> +			goto _irq_set;
> +
> +		err = I2C_READ_DATA(client, TPM_INT_STATUS, &intmask, 1);
> +		if (err < 0)
> +			goto _irq_set;
> +
> +		chip->vendor.irq = interrupts;
> +
> +		tpm_gen_interrupt(chip);
> +	}
> +
> +	tpm_get_timeouts(chip);
> +
> +	i2c_set_clientdata(client, chip);
> +	platform_data->bChipF = false;
> +
> +	dev_info(chip->dev, "TPM I2C Initialized\n");
> +	return 0;
> +_irq_set:
> +	free_irq(gpio_to_irq(platform_data->io_serirq), (void *) chip);
> +_gpio_init2:
> +	if (platform_data && interrupts)
> +		gpio_free(platform_data->io_serirq);
> +_gpio_init1:
> +	if (platform_data && power_mgt)
> +		gpio_free(platform_data->io_lpcpd);
> +_tpm_clean_response:
> +	tpm_remove_hardware(chip->dev);
> +	if (platform_data->tpm_i2c_buffer[1] != NULL) {
> +		kzfree(platform_data->tpm_i2c_buffer[1]);
> +		platform_data->tpm_i2c_buffer[1] = NULL;
> +	}
> +_tpm_clean_answer:
> +	if (platform_data->tpm_i2c_buffer[0] != NULL) {
> +		kzfree(platform_data->tpm_i2c_buffer[0]);
> +		platform_data->tpm_i2c_buffer[0] = NULL;
> +	}
> +
> +	platform_data->bChipF = true;
> +end:
> +	pr_info("TPM I2C initialisation fail\n");
> +	return err;
> +}
> +
> +/*
> + * tpm_st33_i2c_remove remove the TPM device
> + * @param: client, the i2c_client drescription (TPM I2C description).
> +		clear_bit(0, &chip->is_open);
> + * @return: 0 in case of success.
> + */
> +static __devexit int tpm_st33_i2c_remove(struct i2c_client *client)
> +{
> +	struct tpm_chip *chip = (struct tpm_chip *)i2c_get_clientdata(client);
> +	struct st33zp24_platform_data *pin_infos =
> +		((struct i2c_client *) chip->vendor.iobase)->dev.platform_data;
> +
> +	if (pin_infos != NULL) {
> +		free_irq(pin_infos->io_serirq, chip);
> +
> +		gpio_free(pin_infos->io_serirq);
> +		gpio_free(pin_infos->io_lpcpd);
> +
> +		if (pin_infos->bChipF != true)
> +			tpm_remove_hardware(chip->dev);
> +		if (pin_infos->tpm_i2c_buffer[1] != NULL) {
> +			kzfree(pin_infos->tpm_i2c_buffer[1]);
> +			pin_infos->tpm_i2c_buffer[1] = NULL;
> +		}
> +		if (pin_infos->tpm_i2c_buffer[0] != NULL) {
> +			kzfree(pin_infos->tpm_i2c_buffer[0]);
> +			pin_infos->tpm_i2c_buffer[0] = NULL;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +/*
> + * tpm_st33_i2c_pm_suspend suspend the TPM device
> + * Added: Work around when suspend and no tpm application is running, suspend
> + * may fail because chip->data_buffer is not set (only set in tpm_open in Linux
> + * TPM core)
> + * @param: client, the i2c_client drescription (TPM I2C description).
> + * @param: mesg, the power management message.
> + * @return: 0 in case of success.
> + */
> +static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
> +{
> +	struct tpm_chip *chip =
> +	    (struct tpm_chip *)i2c_get_clientdata(client);
> +	struct st33zp24_platform_data *pin_infos =
> +		((struct i2c_client *)chip->vendor.iobase)->dev.platform_data;
> +	int ret = 0;
> +
> +	if (power_mgt)
> +		gpio_set_value(pin_infos->io_lpcpd, 0);
> +	else{
> +		if (chip->data_buffer == NULL)
> +			chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
> +		ret = tpm_pm_suspend(&client->dev);
> +	}
> +	return ret;
> +}				/* tpm_st33_i2c_suspend() */
> +
> +/*
> + * tpm_st33_i2c_pm_resume resume the TPM device
> + * @param: client, the i2c_client drescription (TPM I2C description).
> + * @return: 0 in case of success.
> + */
> +static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
> +{
> +	struct tpm_chip *chip =
> +	    (struct tpm_chip *)i2c_get_clientdata(client);
> +	struct st33zp24_platform_data *pin_infos =
> +		((struct i2c_client *)chip->vendor.iobase)->dev.platform_data;
> +
> +	int ret = 0;
> +
> +	if (power_mgt) {
> +		gpio_set_value(pin_infos->io_lpcpd, 1);
> +		ret = wait_for_serirq_timeout(chip,
> +					  (chip->vendor.status(chip) &&
> +					  TPM_STS_VALID) == TPM_STS_VALID,
> +					  chip->vendor.timeout_b);
> +	} else{
> +	if (chip->data_buffer == NULL)
> +		chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
> +	ret = tpm_pm_resume(&client->dev);
> +	if (!ret)
> +		tpm_do_selftest(chip);
> +	}
> +	return ret;
> +}				/* tpm_st33_i2c_pm_resume() */
> +
> +static const struct i2c_device_id tpm_st33_i2c_id[] = {
> +	{TPM_ST33_I2C, 0},
> +	{}
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, tpm_st33_i2c_id);
> +
> +static struct i2c_driver tpm_st33_i2c_driver = {
> +	.driver = {
> +		   .owner = THIS_MODULE,
> +		   .name = TPM_ST33_I2C,
> +		   },
> +	.probe = tpm_st33_i2c_probe,
> +	.remove = tpm_st33_i2c_remove,
> +	.resume = tpm_st33_i2c_pm_resume,
> +	.suspend = tpm_st33_i2c_pm_suspend,
> +	.id_table = tpm_st33_i2c_id
> +};
> +
> +/*
> + * tpm_st33_i2c_init initialize driver
> + * @return: 0 if successful, else non zero value.
> + */
> +static int __init tpm_st33_i2c_init(void)
> +{
> +	return i2c_add_driver(&tpm_st33_i2c_driver);
> +}
> +
> +/*
> + * tpm_st33_i2c_exit The kernel calls this function during unloading the
> + * module or during shut down process
> + */
> +static void __exit tpm_st33_i2c_exit(void)
> +{
> +	i2c_del_driver(&tpm_st33_i2c_driver);
> +}
> +
> +module_init(tpm_st33_i2c_init);
> +module_exit(tpm_st33_i2c_exit);
> +
> +MODULE_AUTHOR("Christophe Ricard (tpmsupport@st.com)");
> +MODULE_DESCRIPTION("STM TPM I2C ST33 Driver");
> +MODULE_VERSION("1.2.0");
> diff --git a/drivers/char/tpm/tpm_stm_st33_i2c.h b/drivers/char/tpm/tpm_stm_st33_i2c.h
> new file mode 100644
> index 0000000..d390542
> --- /dev/null
> +++ b/drivers/char/tpm/tpm_stm_st33_i2c.h
> @@ -0,0 +1,81 @@
> +/*
> + * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
> + * Copyright (C) 2009, 2010  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, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + *
> + * STMicroelectronics version 1.2.0, Copyright (C) 2010
> + * STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
> + * This is free software, and you are welcome to redistribute it
> + * under certain conditions.
> + *
> + * @Author: Christophe RICARD tpmsupport@st.com
> + *
> + * @File: stm_st33_tpm_i2c.h
> + *
> + * @Date: 09/15/2010
> + */
> +#ifndef __STM_ST33_TPM_I2C_MAIN_H__
> +#define __STM_ST33_TPM_I2C_MAIN_H__
> +
> +#include <linux/pci.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/i2c.h>
> +#include <linux/fs.h>
> +#include <linux/miscdevice.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/delay.h>
> +#include <linux/init.h>
> +#include <linux/wait.h>
> +#include <linux/string.h>
> +#include <linux/interrupt.h>
> +#include <linux/spinlock.h>
> +#include <linux/sysfs.h>
> +#include <linux/gpio.h>
> +#include <linux/sched.h>
> +#include <linux/uaccess.h>
> +#include <linux/io.h>
> +#include <linux/slab.h>
> +#include <linux/sched.h>
> +
> +#include "tpm.h"
> +
> +#define MINOR_NUM_I2C		224
> +
> +#define TPM_ACCESS			(0x0)
> +#define TPM_STS				(0x18)
> +#define TPM_HASH_END			(0x20)
> +#define TPM_DATA_FIFO			(0x24)
> +#define TPM_HASH_DATA			(0x24)
> +#define TPM_HASH_START			(0x28)
> +#define TPM_INTF_CAPABILITY		(0x14)
> +#define TPM_INT_STATUS			(0x10)
> +#define TPM_INT_ENABLE			(0x08)
> +
> +#define TPM_DUMMY_BYTE			0xAA
> +#define TPM_WRITE_DIRECTION		0x80
> +#define TPM_HEADER_SIZE			10
> +#define TPM_BUFSIZE			2048
> +
> +#define LOCALITY0		0
> +
> +struct st_tpm_hash {
> +	int size;
> +	u8 *data;
> +};
> +
> +#endif /* __STM_ST33_TPM_I2C_MAIN_H__ */
> diff --git a/include/linux/i2c/tpm_stm_st33_i2c.h b/include/linux/i2c/tpm_stm_st33_i2c.h
> new file mode 100644
> index 0000000..e3ce42d
> --- /dev/null
> +++ b/include/linux/i2c/tpm_stm_st33_i2c.h
> @@ -0,0 +1,47 @@
> +/*
> +* STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
> +* Copyright (C) 2009, 2010 STMicroelectronics
> +* Christophe RICARD tpmsupport@st.com
> +* 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, write to the Free Software Foundation, Inc.,
> +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> +*
> +* STMicroelectronics version 1.2.0, Copyright (C) 2010
> +* STMicroelectronics comes with ABSOLUTELY NO WARRANTY.
> +* This is free software, and you are welcome to redistribute it
> +* under certain conditions.
> +*
> +* @File: stm_st33_tpm_i2c.h
> +*
> +* @Date: 06/15/2008
> +*/
> +#ifndef __STM_ST33_TPM_I2C_H__
> +#define __STM_ST33_TPM_I2C_H__
> +
> +#include <linux/i2c.h>
> +
> +#define TPM_ST33_I2C			"st33zp24_i2c"
> +#define TPM_I2C_ST33_ADDR_WR_LOC0	(0x26 >> 1)
> +
> +
> +struct st33zp24_platform_data {
> +	int io_serirq;
> +	int io_lpcpd;
> +	struct i2c_client *client;
> +	bool bChipF;
> +	u8 *tpm_i2c_buffer[2]; /* 0 Request 1 Response */
> +	struct completion irq_detection;
> +	struct mutex lock;
> +};
> +
> +#endif /* __STM_ST33_TPM_I2C_H__ */
> -- 
> 1.7.9.5
> 


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

* Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-11-28 17:48           ` Mathias LEBLANC
  2012-11-28 19:04             ` Kent Yoder
@ 2012-11-29  0:04             ` Peter Hüwe
  2012-12-05 16:11               ` Mathias LEBLANC
  1 sibling, 1 reply; 33+ messages in thread
From: Peter Hüwe @ 2012-11-29  0:04 UTC (permalink / raw)
  To: Mathias LEBLANC
  Cc: Kent Yoder, Kent Yoder, Jean-Luc BLANC, linux-kernel,
	Rajiv Andrade, tpmdd-devel, Sirrix

Hi Mathias,

please note: 
I'm writing this email on behalf of myself only and nobody else, especially not my employer - and I'm doing this in my spare time.
I'm working for a direct competitor of yours, but I'm not using any knowledge that I've picked up at work or that is considered secret in any way.
I have a personal interest in the TPM subsystem and want to keep it as clean as possible.
So please don't see my review as something negative, but rather something positive.


Am Mittwoch, 28. November 2012, 18:48:57 schrieb Mathias LEBLANC:
> Ok, so i have patch the ST33 I2C driver on this branch and correct some
> errors. I send you the patch for the kernel 3.x
> I have no error on compilation, tell me if you have problems.
> I have implemented the tpm_do_selftest function to get the tpm ready, but
> it can be removed ________________________________________

Unfortunately you attached the patch instead of sending it in plaintext which is the usual practice -> care to resend in plain text? 
Makes the review far easier.

(btw.: Please also have a look at
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmittingPatches;hb=HEAD
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmitChecklist;hb=HEAD
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmittingDrivers;hb=HEAD
which describes the process in detail)

When you resend the patch, can you please include the "metadata" as well - i.e. your modifications to the Kconfig / Makefile etc.
I do not see a reason why to keep it in a seperate patch.




I tried the patch you've posted and it applies cleanly and now (finally) compiles as well - so now I can start with my review:

= The name =
There's already one i2c tpm driver in the tree, so maybe it would be a good idea to keep the naming scheme consistent? 
-> How about tpm_i2c_stm_st33.c ?
Eventually this is something Kent as a maintainer has to decice - but I would really like to see the name change.
I hope we can eventually consolidate all the 'tis' based drivers.


= Compiling / License = 
When compiling the driver I get the following warning
   WARNING: modpost: missing MODULE_LICENSE() in /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.o
Please include the appropriate MODULE_LICENSE as my kernel otherwise gets tainted by your driver.

Also this:
+ * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
+ * Copyright (C) 2009, 2010  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.

is not possible afaik - kernel code must be under GPL v2 _only_ without the "or (at your option) any later version." addition.



= sparse warnings =
When running sparse against your code I get the following warnings:
 make -C /data/data-old/linux-2.6/ M=`pwd`  modules C=1
make: Entering directory `/data/data-old/linux-2.6'
  CHECK   /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:167:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:187:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:180:5: warning: symbol 'wait_for_serirq_timeout' was not declared. Should it be static?
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:210:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:227:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:245:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:269:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:307:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:324:38: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:394:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:424:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:456:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:531:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:672:29: warning: incorrect type in assignment (different address spaces)
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:672:29:    expected void [noderef] <asn:2>*iobase
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:672:29:    got struct i2c_client *client
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:781:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:818:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:841:19: warning: cast removes address space of expression
  CC [M]  /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.o
  Building modules, stage 2.
  MODPOST 8 modules


Please fix these if applicable - otherwise you'll probably get a friendly reminder to do so by fengguang's build test ;)


= smatch =
Same applies to smatch
make -C /data/data-old/linux-2.6/ M=`pwd`  modules C=1 CHECK=smatch
make: Entering directory `/data/data-old/linux-2.6'
  CHECK   /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:535 tpm_stm_i2c_recv() warn: variable dereferenced before check 'chip' (see line 531)
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:748 tpm_st33_i2c_probe() warn: variable dereferenced before check 'platform_data' (see line 659)
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:848 tpm_st33_i2c_pm_resume() warn: should this be a bitwise op?
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:848 tpm_st33_i2c_pm_resume() warn: should this be a bitwise op?
  CC [M]  /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.o

Please fix these if applicable - otherwise you'll probably get a friendly reminder to do so by fengguang's build test ;)

= checkpatch =
Also please run .../scripts/checkpatch.pl -strict before submission - not everything that is reported might be applicable, but quite often it is.



Looking forward to your v2 so I can give a more detailed code review of your code.


Thanks,
Peter



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

* RE: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-11-29  0:04             ` Peter Hüwe
@ 2012-12-05 16:11               ` Mathias LEBLANC
  2012-12-05 17:13                 ` Kent Yoder
  0 siblings, 1 reply; 33+ messages in thread
From: Mathias LEBLANC @ 2012-12-05 16:11 UTC (permalink / raw)
  To: Peter Hüwe
  Cc: Kent Yoder, Kent Yoder, Jean-Luc BLANC, linux-kernel,
	Rajiv Andrade, tpmdd-devel, Sirrix

Hi Peter,

Thanks for your contribution.
I have modified the driver files name and descriptions.
Regarding the warnings, it's strange. 

@Kent, could you confirm that you have the same?

Regards,

Mathias Leblanc

-----Original Message-----
From: Peter Hüwe [mailto:PeterHuewe@gmx.de] 
Sent: 29 November, 2012 01:05
To: Mathias LEBLANC
Cc: Kent Yoder; Kent Yoder; Jean-Luc BLANC; linux-kernel@vger.kernel.org; Rajiv Andrade; tpmdd-devel@lists.sourceforge.net; Sirrix@jasper.es
Subject: Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x

Hi Mathias,

please note: 
I'm writing this email on behalf of myself only and nobody else, especially not my employer - and I'm doing this in my spare time.
I'm working for a direct competitor of yours, but I'm not using any knowledge that I've picked up at work or that is considered secret in any way.
I have a personal interest in the TPM subsystem and want to keep it as clean as possible.
So please don't see my review as something negative, but rather something positive.


Am Mittwoch, 28. November 2012, 18:48:57 schrieb Mathias LEBLANC:
> Ok, so i have patch the ST33 I2C driver on this branch and correct 
> some errors. I send you the patch for the kernel 3.x I have no error 
> on compilation, tell me if you have problems.
> I have implemented the tpm_do_selftest function to get the tpm ready, 
> but it can be removed ________________________________________

Unfortunately you attached the patch instead of sending it in plaintext which is the usual practice -> care to resend in plain text? 
Makes the review far easier.

(btw.: Please also have a look at
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmittingPatches;hb=HEAD
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmitChecklist;hb=HEAD
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmittingDrivers;hb=HEAD
which describes the process in detail)

When you resend the patch, can you please include the "metadata" as well - i.e. your modifications to the Kconfig / Makefile etc.
I do not see a reason why to keep it in a seperate patch.




I tried the patch you've posted and it applies cleanly and now (finally) compiles as well - so now I can start with my review:

= The name =
There's already one i2c tpm driver in the tree, so maybe it would be a good idea to keep the naming scheme consistent? 
-> How about tpm_i2c_stm_st33.c ?
Eventually this is something Kent as a maintainer has to decice - but I would really like to see the name change.
I hope we can eventually consolidate all the 'tis' based drivers.


= Compiling / License =
When compiling the driver I get the following warning
   WARNING: modpost: missing MODULE_LICENSE() in /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.o
Please include the appropriate MODULE_LICENSE as my kernel otherwise gets tainted by your driver.

Also this:
+ * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
+ * Copyright (C) 2009, 2010  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.

is not possible afaik - kernel code must be under GPL v2 _only_ without the "or (at your option) any later version." addition.



= sparse warnings =
When running sparse against your code I get the following warnings:
 make -C /data/data-old/linux-2.6/ M=`pwd`  modules C=1
make: Entering directory `/data/data-old/linux-2.6'
  CHECK   /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:167:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:187:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:180:5: warning: symbol 'wait_for_serirq_timeout' was not declared. Should it be static?
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:210:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:227:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:245:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:269:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:307:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:324:38: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:394:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:424:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:456:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:531:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:672:29: warning: incorrect type in assignment (different address spaces)
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:672:29:    expected void [noderef] <asn:2>*iobase
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:672:29:    got struct i2c_client *client
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:781:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:818:19: warning: cast removes address space of expression
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:841:19: warning: cast removes address space of expression
  CC [M]  /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.o
  Building modules, stage 2.
  MODPOST 8 modules


Please fix these if applicable - otherwise you'll probably get a friendly reminder to do so by fengguang's build test ;)


= smatch =
Same applies to smatch
make -C /data/data-old/linux-2.6/ M=`pwd`  modules C=1 CHECK=smatch
make: Entering directory `/data/data-old/linux-2.6'
  CHECK   /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:535 tpm_stm_i2c_recv() warn: variable dereferenced before check 'chip' (see line 531)
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:748 tpm_st33_i2c_probe() warn: variable dereferenced before check 'platform_data' (see line 659)
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:848 tpm_st33_i2c_pm_resume() warn: should this be a bitwise op?
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:848 tpm_st33_i2c_pm_resume() warn: should this be a bitwise op?
  CC [M]  /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.o

Please fix these if applicable - otherwise you'll probably get a friendly reminder to do so by fengguang's build test ;)

= checkpatch =
Also please run .../scripts/checkpatch.pl -strict before submission - not everything that is reported might be applicable, but quite often it is.



Looking forward to your v2 so I can give a more detailed code review of your code.


Thanks,
Peter



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

* Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-12-05 16:11               ` Mathias LEBLANC
@ 2012-12-05 17:13                 ` Kent Yoder
  2012-12-05 17:45                   ` Kent Yoder
  0 siblings, 1 reply; 33+ messages in thread
From: Kent Yoder @ 2012-12-05 17:13 UTC (permalink / raw)
  To: Mathias LEBLANC
  Cc: Peter Hüwe, Kent Yoder, Jean-Luc BLANC, linux-kernel,
	Rajiv Andrade, tpmdd-devel, Sirrix

On Wed, Dec 05, 2012 at 05:11:40PM +0100, Mathias LEBLANC wrote:
> Hi Peter,
> 
> Thanks for your contribution.
> I have modified the driver files name and descriptions.
> Regarding the warnings, it's strange. 
> 
> @Kent, could you confirm that you have the same?

  Yep, I see these too. They're a side effect of storing the i2c_client
pointer in vendor->iobase, which is __iomem.  The i2c_client struct
isn't __iomem at all though, writes in the i2c subsystem are done
through client->addr.  So i2c_client should really be stored somewhere
else, no?

  vendor->data seems like the right place.  I'm on the hook to update
the other drivers with a macro for accessing vendor->data in tpm.h.
I'll make these updates and send out a patch.

Kent

> Regards,
> 
> Mathias Leblanc
> 
> -----Original Message-----
> From: Peter Hüwe [mailto:PeterHuewe@gmx.de] 
> Sent: 29 November, 2012 01:05
> To: Mathias LEBLANC
> Cc: Kent Yoder; Kent Yoder; Jean-Luc BLANC; linux-kernel@vger.kernel.org; Rajiv Andrade; tpmdd-devel@lists.sourceforge.net; Sirrix@jasper.es
> Subject: Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
> 
> Hi Mathias,
> 
> please note: 
> I'm writing this email on behalf of myself only and nobody else, especially not my employer - and I'm doing this in my spare time.
> I'm working for a direct competitor of yours, but I'm not using any knowledge that I've picked up at work or that is considered secret in any way.
> I have a personal interest in the TPM subsystem and want to keep it as clean as possible.
> So please don't see my review as something negative, but rather something positive.
> 
> 
> Am Mittwoch, 28. November 2012, 18:48:57 schrieb Mathias LEBLANC:
> > Ok, so i have patch the ST33 I2C driver on this branch and correct 
> > some errors. I send you the patch for the kernel 3.x I have no error 
> > on compilation, tell me if you have problems.
> > I have implemented the tpm_do_selftest function to get the tpm ready, 
> > but it can be removed ________________________________________
> 
> Unfortunately you attached the patch instead of sending it in plaintext which is the usual practice -> care to resend in plain text? 
> Makes the review far easier.
> 
> (btw.: Please also have a look at
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmittingPatches;hb=HEAD
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmitChecklist;hb=HEAD
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmittingDrivers;hb=HEAD
> which describes the process in detail)
> 
> When you resend the patch, can you please include the "metadata" as well - i.e. your modifications to the Kconfig / Makefile etc.
> I do not see a reason why to keep it in a seperate patch.
> 
> 
> 
> 
> I tried the patch you've posted and it applies cleanly and now (finally) compiles as well - so now I can start with my review:
> 
> = The name =
> There's already one i2c tpm driver in the tree, so maybe it would be a good idea to keep the naming scheme consistent? 
> -> How about tpm_i2c_stm_st33.c ?
> Eventually this is something Kent as a maintainer has to decice - but I would really like to see the name change.
> I hope we can eventually consolidate all the 'tis' based drivers.
> 
> 
> = Compiling / License =
> When compiling the driver I get the following warning
>    WARNING: modpost: missing MODULE_LICENSE() in /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.o
> Please include the appropriate MODULE_LICENSE as my kernel otherwise gets tainted by your driver.
> 
> Also this:
> + * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
> + * Copyright (C) 2009, 2010  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.
> 
> is not possible afaik - kernel code must be under GPL v2 _only_ without the "or (at your option) any later version." addition.
> 
> 
> 
> = sparse warnings =
> When running sparse against your code I get the following warnings:
>  make -C /data/data-old/linux-2.6/ M=`pwd`  modules C=1
> make: Entering directory `/data/data-old/linux-2.6'
>   CHECK   /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:167:19: warning: cast removes address space of expression
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:187:19: warning: cast removes address space of expression
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:180:5: warning: symbol 'wait_for_serirq_timeout' was not declared. Should it be static?
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:210:19: warning: cast removes address space of expression
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:227:19: warning: cast removes address space of expression
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:245:19: warning: cast removes address space of expression
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:269:19: warning: cast removes address space of expression
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:307:19: warning: cast removes address space of expression
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:324:38: warning: cast removes address space of expression
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:394:19: warning: cast removes address space of expression
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:424:19: warning: cast removes address space of expression
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:456:19: warning: cast removes address space of expression
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:531:19: warning: cast removes address space of expression
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:672:29: warning: incorrect type in assignment (different address spaces)
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:672:29:    expected void [noderef] <asn:2>*iobase
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:672:29:    got struct i2c_client *client
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:781:19: warning: cast removes address space of expression
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:818:19: warning: cast removes address space of expression
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:841:19: warning: cast removes address space of expression
>   CC [M]  /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.o
>   Building modules, stage 2.
>   MODPOST 8 modules
> 
> 
> Please fix these if applicable - otherwise you'll probably get a friendly reminder to do so by fengguang's build test ;)
> 
> 
> = smatch =
> Same applies to smatch
> make -C /data/data-old/linux-2.6/ M=`pwd`  modules C=1 CHECK=smatch
> make: Entering directory `/data/data-old/linux-2.6'
>   CHECK   /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:535 tpm_stm_i2c_recv() warn: variable dereferenced before check 'chip' (see line 531)
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:748 tpm_st33_i2c_probe() warn: variable dereferenced before check 'platform_data' (see line 659)
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:848 tpm_st33_i2c_pm_resume() warn: should this be a bitwise op?
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:848 tpm_st33_i2c_pm_resume() warn: should this be a bitwise op?
>   CC [M]  /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.o
> 
> Please fix these if applicable - otherwise you'll probably get a friendly reminder to do so by fengguang's build test ;)
> 
> = checkpatch =
> Also please run .../scripts/checkpatch.pl -strict before submission - not everything that is reported might be applicable, but quite often it is.
> 
> 
> 
> Looking forward to your v2 so I can give a more detailed code review of your code.
> 
> 
> Thanks,
> Peter
> 
> 


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

* Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-12-05 17:13                 ` Kent Yoder
@ 2012-12-05 17:45                   ` Kent Yoder
  2012-12-05 18:07                     ` Kent Yoder
  0 siblings, 1 reply; 33+ messages in thread
From: Kent Yoder @ 2012-12-05 17:45 UTC (permalink / raw)
  To: Mathias LEBLANC
  Cc: Jean-Luc BLANC, Sirrix, linux-kernel, Rajiv Andrade, tpmdd-devel,
	Peter Hüwe, Kent Yoder

On Wed, Dec 05, 2012 at 11:13:51AM -0600, Kent Yoder wrote:
> On Wed, Dec 05, 2012 at 05:11:40PM +0100, Mathias LEBLANC wrote:
> > Hi Peter,
> > 
> > Thanks for your contribution.
> > I have modified the driver files name and descriptions.
> > Regarding the warnings, it's strange. 
> > 
> > @Kent, could you confirm that you have the same?
> 
>   Yep, I see these too. They're a side effect of storing the i2c_client
> pointer in vendor->iobase, which is __iomem.  The i2c_client struct
> isn't __iomem at all though, writes in the i2c subsystem are done
> through client->addr.  So i2c_client should really be stored somewhere
> else, no?
> 
>   vendor->data seems like the right place.  I'm on the hook to update
> the other drivers with a macro for accessing vendor->data in tpm.h.
> I'll make these updates and send out a patch.

  Mathias, one other thing, MODULE_LICENSE(): GPL?

Kent

> Kent
> 
> > Regards,
> > 
> > Mathias Leblanc
> > 
> > -----Original Message-----
> > From: Peter Hüwe [mailto:PeterHuewe@gmx.de] 
> > Sent: 29 November, 2012 01:05
> > To: Mathias LEBLANC
> > Cc: Kent Yoder; Kent Yoder; Jean-Luc BLANC; linux-kernel@vger.kernel.org; Rajiv Andrade; tpmdd-devel@lists.sourceforge.net; Sirrix@jasper.es
> > Subject: Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
> > 
> > Hi Mathias,
> > 
> > please note: 
> > I'm writing this email on behalf of myself only and nobody else, especially not my employer - and I'm doing this in my spare time.
> > I'm working for a direct competitor of yours, but I'm not using any knowledge that I've picked up at work or that is considered secret in any way.
> > I have a personal interest in the TPM subsystem and want to keep it as clean as possible.
> > So please don't see my review as something negative, but rather something positive.
> > 
> > 
> > Am Mittwoch, 28. November 2012, 18:48:57 schrieb Mathias LEBLANC:
> > > Ok, so i have patch the ST33 I2C driver on this branch and correct 
> > > some errors. I send you the patch for the kernel 3.x I have no error 
> > > on compilation, tell me if you have problems.
> > > I have implemented the tpm_do_selftest function to get the tpm ready, 
> > > but it can be removed ________________________________________
> > 
> > Unfortunately you attached the patch instead of sending it in plaintext which is the usual practice -> care to resend in plain text? 
> > Makes the review far easier.
> > 
> > (btw.: Please also have a look at
> > http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmittingPatches;hb=HEAD
> > http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmitChecklist;hb=HEAD
> > http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmittingDrivers;hb=HEAD
> > which describes the process in detail)
> > 
> > When you resend the patch, can you please include the "metadata" as well - i.e. your modifications to the Kconfig / Makefile etc.
> > I do not see a reason why to keep it in a seperate patch.
> > 
> > 
> > 
> > 
> > I tried the patch you've posted and it applies cleanly and now (finally) compiles as well - so now I can start with my review:
> > 
> > = The name =
> > There's already one i2c tpm driver in the tree, so maybe it would be a good idea to keep the naming scheme consistent? 
> > -> How about tpm_i2c_stm_st33.c ?
> > Eventually this is something Kent as a maintainer has to decice - but I would really like to see the name change.
> > I hope we can eventually consolidate all the 'tis' based drivers.
> > 
> > 
> > = Compiling / License =
> > When compiling the driver I get the following warning
> >    WARNING: modpost: missing MODULE_LICENSE() in /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.o
> > Please include the appropriate MODULE_LICENSE as my kernel otherwise gets tainted by your driver.
> > 
> > Also this:
> > + * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
> > + * Copyright (C) 2009, 2010  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.
> > 
> > is not possible afaik - kernel code must be under GPL v2 _only_ without the "or (at your option) any later version." addition.
> > 
> > 
> > 
> > = sparse warnings =
> > When running sparse against your code I get the following warnings:
> >  make -C /data/data-old/linux-2.6/ M=`pwd`  modules C=1
> > make: Entering directory `/data/data-old/linux-2.6'
> >   CHECK   /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:167:19: warning: cast removes address space of expression
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:187:19: warning: cast removes address space of expression
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:180:5: warning: symbol 'wait_for_serirq_timeout' was not declared. Should it be static?
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:210:19: warning: cast removes address space of expression
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:227:19: warning: cast removes address space of expression
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:245:19: warning: cast removes address space of expression
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:269:19: warning: cast removes address space of expression
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:307:19: warning: cast removes address space of expression
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:324:38: warning: cast removes address space of expression
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:394:19: warning: cast removes address space of expression
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:424:19: warning: cast removes address space of expression
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:456:19: warning: cast removes address space of expression
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:531:19: warning: cast removes address space of expression
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:672:29: warning: incorrect type in assignment (different address spaces)
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:672:29:    expected void [noderef] <asn:2>*iobase
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:672:29:    got struct i2c_client *client
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:781:19: warning: cast removes address space of expression
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:818:19: warning: cast removes address space of expression
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:841:19: warning: cast removes address space of expression
> >   CC [M]  /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.o
> >   Building modules, stage 2.
> >   MODPOST 8 modules
> > 
> > 
> > Please fix these if applicable - otherwise you'll probably get a friendly reminder to do so by fengguang's build test ;)
> > 
> > 
> > = smatch =
> > Same applies to smatch
> > make -C /data/data-old/linux-2.6/ M=`pwd`  modules C=1 CHECK=smatch
> > make: Entering directory `/data/data-old/linux-2.6'
> >   CHECK   /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:535 tpm_stm_i2c_recv() warn: variable dereferenced before check 'chip' (see line 531)
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:748 tpm_st33_i2c_probe() warn: variable dereferenced before check 'platform_data' (see line 659)
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:848 tpm_st33_i2c_pm_resume() warn: should this be a bitwise op?
> > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:848 tpm_st33_i2c_pm_resume() warn: should this be a bitwise op?
> >   CC [M]  /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.o
> > 
> > Please fix these if applicable - otherwise you'll probably get a friendly reminder to do so by fengguang's build test ;)
> > 
> > = checkpatch =
> > Also please run .../scripts/checkpatch.pl -strict before submission - not everything that is reported might be applicable, but quite often it is.
> > 
> > 
> > 
> > Looking forward to your v2 so I can give a more detailed code review of your code.
> > 
> > 
> > Thanks,
> > Peter
> > 
> > 
> 
> 
> ------------------------------------------------------------------------------
> LogMeIn Rescue: Anywhere, Anytime Remote support for IT. Free Trial
> Remotely access PCs and mobile devices and provide instant support
> Improve your efficiency, and focus on delivering more value-add services
> Discover what IT Professionals Know. Rescue delivers
> http://p.sf.net/sfu/logmein_12329d2d
> _______________________________________________
> tpmdd-devel mailing list
> tpmdd-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/tpmdd-devel
> 


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

* Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-12-05 17:45                   ` Kent Yoder
@ 2012-12-05 18:07                     ` Kent Yoder
  2012-12-05 20:20                       ` Peter Hüwe
  2012-12-05 21:14                       ` Peter Hüwe
  0 siblings, 2 replies; 33+ messages in thread
From: Kent Yoder @ 2012-12-05 18:07 UTC (permalink / raw)
  To: Mathias LEBLANC
  Cc: Jean-Luc BLANC, Sirrix, linux-kernel, Rajiv Andrade, tpmdd-devel,
	Peter Hüwe, Kent Yoder

On Wed, Dec 05, 2012 at 11:45:27AM -0600, Kent Yoder wrote:
> On Wed, Dec 05, 2012 at 11:13:51AM -0600, Kent Yoder wrote:
> > On Wed, Dec 05, 2012 at 05:11:40PM +0100, Mathias LEBLANC wrote:
> > > Hi Peter,
> > > 
> > > Thanks for your contribution.
> > > I have modified the driver files name and descriptions.
> > > Regarding the warnings, it's strange. 
> > > 
> > > @Kent, could you confirm that you have the same?
> > 
> >   Yep, I see these too. They're a side effect of storing the i2c_client
> > pointer in vendor->iobase, which is __iomem.  The i2c_client struct
> > isn't __iomem at all though, writes in the i2c subsystem are done
> > through client->addr.  So i2c_client should really be stored somewhere
> > else, no?
> > 
> >   vendor->data seems like the right place.  I'm on the hook to update
> > the other drivers with a macro for accessing vendor->data in tpm.h.
> > I'll make these updates and send out a patch.
> 
>   Mathias, one other thing, MODULE_LICENSE(): GPL?

  Heh, duh, well of course it is. I've now staged everything I'm
planning on pushing at:

git://github.com/shpedoikal/linux.git tpmdd-12-05-12

Please test and let me know if I missed anything.

Thanks,
Kent

> 
> Kent
> 
> > Kent
> > 
> > > Regards,
> > > 
> > > Mathias Leblanc
> > > 
> > > -----Original Message-----
> > > From: Peter Hüwe [mailto:PeterHuewe@gmx.de] 
> > > Sent: 29 November, 2012 01:05
> > > To: Mathias LEBLANC
> > > Cc: Kent Yoder; Kent Yoder; Jean-Luc BLANC; linux-kernel@vger.kernel.org; Rajiv Andrade; tpmdd-devel@lists.sourceforge.net; Sirrix@jasper.es
> > > Subject: Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
> > > 
> > > Hi Mathias,
> > > 
> > > please note: 
> > > I'm writing this email on behalf of myself only and nobody else, especially not my employer - and I'm doing this in my spare time.
> > > I'm working for a direct competitor of yours, but I'm not using any knowledge that I've picked up at work or that is considered secret in any way.
> > > I have a personal interest in the TPM subsystem and want to keep it as clean as possible.
> > > So please don't see my review as something negative, but rather something positive.
> > > 
> > > 
> > > Am Mittwoch, 28. November 2012, 18:48:57 schrieb Mathias LEBLANC:
> > > > Ok, so i have patch the ST33 I2C driver on this branch and correct 
> > > > some errors. I send you the patch for the kernel 3.x I have no error 
> > > > on compilation, tell me if you have problems.
> > > > I have implemented the tpm_do_selftest function to get the tpm ready, 
> > > > but it can be removed ________________________________________
> > > 
> > > Unfortunately you attached the patch instead of sending it in plaintext which is the usual practice -> care to resend in plain text? 
> > > Makes the review far easier.
> > > 
> > > (btw.: Please also have a look at
> > > http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmittingPatches;hb=HEAD
> > > http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmitChecklist;hb=HEAD
> > > http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=Documentation/SubmittingDrivers;hb=HEAD
> > > which describes the process in detail)
> > > 
> > > When you resend the patch, can you please include the "metadata" as well - i.e. your modifications to the Kconfig / Makefile etc.
> > > I do not see a reason why to keep it in a seperate patch.
> > > 
> > > 
> > > 
> > > 
> > > I tried the patch you've posted and it applies cleanly and now (finally) compiles as well - so now I can start with my review:
> > > 
> > > = The name =
> > > There's already one i2c tpm driver in the tree, so maybe it would be a good idea to keep the naming scheme consistent? 
> > > -> How about tpm_i2c_stm_st33.c ?
> > > Eventually this is something Kent as a maintainer has to decice - but I would really like to see the name change.
> > > I hope we can eventually consolidate all the 'tis' based drivers.
> > > 
> > > 
> > > = Compiling / License =
> > > When compiling the driver I get the following warning
> > >    WARNING: modpost: missing MODULE_LICENSE() in /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.o
> > > Please include the appropriate MODULE_LICENSE as my kernel otherwise gets tainted by your driver.
> > > 
> > > Also this:
> > > + * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
> > > + * Copyright (C) 2009, 2010  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.
> > > 
> > > is not possible afaik - kernel code must be under GPL v2 _only_ without the "or (at your option) any later version." addition.
> > > 
> > > 
> > > 
> > > = sparse warnings =
> > > When running sparse against your code I get the following warnings:
> > >  make -C /data/data-old/linux-2.6/ M=`pwd`  modules C=1
> > > make: Entering directory `/data/data-old/linux-2.6'
> > >   CHECK   /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:167:19: warning: cast removes address space of expression
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:187:19: warning: cast removes address space of expression
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:180:5: warning: symbol 'wait_for_serirq_timeout' was not declared. Should it be static?
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:210:19: warning: cast removes address space of expression
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:227:19: warning: cast removes address space of expression
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:245:19: warning: cast removes address space of expression
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:269:19: warning: cast removes address space of expression
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:307:19: warning: cast removes address space of expression
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:324:38: warning: cast removes address space of expression
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:394:19: warning: cast removes address space of expression
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:424:19: warning: cast removes address space of expression
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:456:19: warning: cast removes address space of expression
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:531:19: warning: cast removes address space of expression
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:672:29: warning: incorrect type in assignment (different address spaces)
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:672:29:    expected void [noderef] <asn:2>*iobase
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:672:29:    got struct i2c_client *client
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:781:19: warning: cast removes address space of expression
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:818:19: warning: cast removes address space of expression
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:841:19: warning: cast removes address space of expression
> > >   CC [M]  /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.o
> > >   Building modules, stage 2.
> > >   MODPOST 8 modules
> > > 
> > > 
> > > Please fix these if applicable - otherwise you'll probably get a friendly reminder to do so by fengguang's build test ;)
> > > 
> > > 
> > > = smatch =
> > > Same applies to smatch
> > > make -C /data/data-old/linux-2.6/ M=`pwd`  modules C=1 CHECK=smatch
> > > make: Entering directory `/data/data-old/linux-2.6'
> > >   CHECK   /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:535 tpm_stm_i2c_recv() warn: variable dereferenced before check 'chip' (see line 531)
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:748 tpm_st33_i2c_probe() warn: variable dereferenced before check 'platform_data' (see line 659)
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:848 tpm_st33_i2c_pm_resume() warn: should this be a bitwise op?
> > > /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:848 tpm_st33_i2c_pm_resume() warn: should this be a bitwise op?
> > >   CC [M]  /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.o
> > > 
> > > Please fix these if applicable - otherwise you'll probably get a friendly reminder to do so by fengguang's build test ;)
> > > 
> > > = checkpatch =
> > > Also please run .../scripts/checkpatch.pl -strict before submission - not everything that is reported might be applicable, but quite often it is.
> > > 
> > > 
> > > 
> > > Looking forward to your v2 so I can give a more detailed code review of your code.
> > > 
> > > 
> > > Thanks,
> > > Peter
> > > 
> > > 
> > 
> > 
> > ------------------------------------------------------------------------------
> > LogMeIn Rescue: Anywhere, Anytime Remote support for IT. Free Trial
> > Remotely access PCs and mobile devices and provide instant support
> > Improve your efficiency, and focus on delivering more value-add services
> > Discover what IT Professionals Know. Rescue delivers
> > http://p.sf.net/sfu/logmein_12329d2d
> > _______________________________________________
> > tpmdd-devel mailing list
> > tpmdd-devel@lists.sourceforge.net
> > https://lists.sourceforge.net/lists/listinfo/tpmdd-devel
> > 
> 
> 
> ------------------------------------------------------------------------------
> LogMeIn Rescue: Anywhere, Anytime Remote support for IT. Free Trial
> Remotely access PCs and mobile devices and provide instant support
> Improve your efficiency, and focus on delivering more value-add services
> Discover what IT Professionals Know. Rescue delivers
> http://p.sf.net/sfu/logmein_12329d2d
> _______________________________________________
> tpmdd-devel mailing list
> tpmdd-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/tpmdd-devel
> 


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

* Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-12-05 18:07                     ` Kent Yoder
@ 2012-12-05 20:20                       ` Peter Hüwe
  2012-12-05 21:00                         ` Kent Yoder
  2012-12-05 21:14                       ` Peter Hüwe
  1 sibling, 1 reply; 33+ messages in thread
From: Peter Hüwe @ 2012-12-05 20:20 UTC (permalink / raw)
  To: Kent Yoder
  Cc: Mathias LEBLANC, Jean-Luc BLANC, Sirrix, linux-kernel,
	Rajiv Andrade, tpmdd-devel, Kent Yoder

Hi Kent,
> 
>   Heh, duh, well of course it is. I've now staged everything I'm
> planning on pushing at:
> 
> git://github.com/shpedoikal/linux.git tpmdd-12-05-12
> 
> Please test and let me know if I missed anything.
> 
> Thanks,
> Kent
> 
> > Kent
> > 

(I'm still writing this on behalf of myself ;)

<pedantic mode on - please don't take it personally>
While I really appreciate you helping Mathias out here, I'm not so sure 
whether an offlist discussion of a driver submission is a really good idea. 
I did not see any v2 / improvements on list and now it's commited (?!)

There's no need to argue here, I'm fine with this,
but I'd highly appreciate if at least the result is published again in the 
future on the mailing list, for proper review. 

If the mailfilter got the mails I apologize.
<pedantic mode off>

Can you perhaps post the message to the list, so a proper review is possible?

I thought the Mathias has changed the naming of the files? I don't see that in 
your commit.


The version you committed to that branch still has some of the items of my 
first review. (e.g.
 * 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.)

-> The (possible) GPL v3 clause has to go away for the kernel, but I'm not a 
lawyer.



Thanks,
Peter

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

* Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-12-05 20:20                       ` Peter Hüwe
@ 2012-12-05 21:00                         ` Kent Yoder
  2012-12-05 21:39                           ` Peter Hüwe
  0 siblings, 1 reply; 33+ messages in thread
From: Kent Yoder @ 2012-12-05 21:00 UTC (permalink / raw)
  To: Peter Hüwe
  Cc: Mathias LEBLANC, Jean-Luc BLANC, Sirrix, linux-kernel,
	Rajiv Andrade, tpmdd-devel, Kent Yoder

On Wed, Dec 05, 2012 at 09:20:47PM +0100, Peter Hüwe wrote:
> Hi Kent,
> > 
> >   Heh, duh, well of course it is. I've now staged everything I'm
> > planning on pushing at:
> > 
> > git://github.com/shpedoikal/linux.git tpmdd-12-05-12
> > 
> > Please test and let me know if I missed anything.
> > 
> > Thanks,
> > Kent
> > 
> > > Kent
> > > 
> 
> (I'm still writing this on behalf of myself ;)
> 
> <pedantic mode on - please don't take it personally>
> While I really appreciate you helping Mathias out here, I'm not so sure 
> whether an offlist discussion of a driver submission is a really good idea. 
> I did not see any v2 / improvements on list and now it's commited (?!)

  This is already at least v3 of the driver IIRC. And its not fully
committed at all, its just in a staging tree. I can blow it away at any
time if we find problems.

> There's no need to argue here, I'm fine with this,
> but I'd highly appreciate if at least the result is published again in the 
> future on the mailing list, for proper review. 

  Not a problem. usually I'd attach any updates I planned to commit for
public review, then if anything wasn't made public before I issue my
pull request to send them to security-next, I'd append the full diff to
the pull request at that time. Either way, all changes will hit a list
at some point in time.

> If the mailfilter got the mails I apologize.
> <pedantic mode off>
> 
> Can you perhaps post the message to the list, so a proper review is possible?
> 
> I thought the Mathias has changed the naming of the files? I don't see that in 
> your commit.

  Good catch, this is the kind of review I was asking for. :-)

> 
> The version you committed to that branch still has some of the items of my 
> first review. (e.g.
>  * 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.)
> 
> -> The (possible) GPL v3 clause has to go away for the kernel, but I'm not a 
> lawyer.

  A GPLv3 clause would say "v3 or any later version". This should be
fine.

Kent

> 
> 
> Thanks,
> Peter
> 


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

* Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-12-05 18:07                     ` Kent Yoder
  2012-12-05 20:20                       ` Peter Hüwe
@ 2012-12-05 21:14                       ` Peter Hüwe
  2012-12-05 23:09                         ` Kent Yoder
  1 sibling, 1 reply; 33+ messages in thread
From: Peter Hüwe @ 2012-12-05 21:14 UTC (permalink / raw)
  To: Kent Yoder
  Cc: Mathias LEBLANC, Jean-Luc BLANC, Sirrix, linux-kernel,
	Rajiv Andrade, tpmdd-devel, Kent Yoder

Hi Kent, Matthias,

Am Mittwoch, 5. Dezember 2012, 19:07:20 schrieb Kent Yoder:
>   Heh, duh, well of course it is. I've now staged everything I'm
> planning on pushing at:
> 
> git://github.com/shpedoikal/linux.git tpmdd-12-05-12
> 
> Please test and let me know if I missed anything.


I just checked out your commit from github.

Here's a part of the review:

Smatch still complains a bit, sparse is fine.:

 make -C /data/data-old/linux-2.6/ M=`pwd` C=1 CHECK=smatch modules
make: Entering directory `/data/data-old/linux-2.6'
  CHECK   /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:535 tpm_stm_i2c_recv() warn: variable dereferenced before check 'chip' (see line 531)
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:748 tpm_st33_i2c_probe() warn: variable dereferenced before check 'platform_data' (see line 659)
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:848 tpm_st33_i2c_pm_resume() warn: should this be a bitwise op?
/data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:848 tpm_st33_i2c_pm_resume() warn: should this be a bitwise op?
  CC [M]  /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.o
  Building modules, stage 2.
  MODPOST 6 modules
  LD [M]  /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.ko
make: Leaving directory `/data/data-old/linux-2.6'

Please check.


(maybe also fix the checkpatch -strict stuff as well? Would be nice ;)





drivers/char/tpm/tpm_stm_st33_i2c.h 
- Does the driver really need a seperate headerfile in drivers/char/tpm/ ? for me it seems everything can be included into the c-file.

> struct st_tpm_hash {
>	int size;
>	u8 *data;
> };
is unused - please remove.

> #define MINOR_NUM_I2C		224
Please remove, it's unused and if you really need it use the one from tpm.h

include/linux/i2c/tpm_stm_st33_i2c.h
I'm not sure if this is needed publicly? Or does only your driver need this?

>struct st33zp24_platform_data {
Telling from the name I have no idea what this device is.





drivers/char/tpm/tpm_stm_st33_i2c.c

>enum stm33zp24_int_flags {
>	TPM_GLOBAL_INT_ENABLE = 0x80,
>	TPM_INTF_CMD_READY_INT = 0x080,
>	TPM_INTF_FIFO_AVALAIBLE_INT = 0x040,
>	TPM_INTF_WAKE_UP_READY_INT = 0x020,
>	TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
>	TPM_INTF_STS_VALID_INT = 0x002,
>	TPM_INTF_DATA_AVAIL_INT = 0x001,
>};

Why the leading zeros? please remove.


> static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
>...
> static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
>,,,
>static struct i2c_driver tpm_st33_i2c_driver = {
>	.driver = {
>		   .owner = THIS_MODULE,
>		   .name = TPM_ST33_I2C,
>		   },
>	.probe = tpm_st33_i2c_probe,
>	.remove = tpm_st33_i2c_remove,
>	.resume = tpm_st33_i2c_pm_resume,
>	.suspend = tpm_st33_i2c_pm_suspend,
>	.id_table = tpm_st33_i2c_id
>};

Please convert resume/suspend  to .driver.pm 

It's pretty easy.
See this post  for details
http://sourceforge.net/mailarchive/message.php?msg_id=29516784
Rafael did spent quite a lot of effort to convert almost every driver back then, so we should 'fix' new ones.



> /*
>  * tpm_st33_i2c_init initialize driver
>  * @return: 0 if successful, else non zero value.
>  */
> static int __init tpm_st33_i2c_init(void)
> {
> 	return i2c_add_driver(&tpm_st33_i2c_driver);
> }
> 
> /*
>  * tpm_st33_i2c_exit The kernel calls this function during unloading the
>  * module or during shut down process
>  */
> static void __exit tpm_st33_i2c_exit(void)
> {
> 	i2c_del_driver(&tpm_st33_i2c_driver);
> }
> 
> module_init(tpm_st33_i2c_init);
> module_exit(tpm_st33_i2c_exit);

Hooray for oneliners ;)
+ module_i2c_driver(tpm_st33_i2c_driver);



Keep on hacking ;)

Thanks,
PeterH



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

* Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-12-05 21:00                         ` Kent Yoder
@ 2012-12-05 21:39                           ` Peter Hüwe
  0 siblings, 0 replies; 33+ messages in thread
From: Peter Hüwe @ 2012-12-05 21:39 UTC (permalink / raw)
  To: Kent Yoder
  Cc: Mathias LEBLANC, Jean-Luc BLANC, Sirrix, linux-kernel,
	Rajiv Andrade, tpmdd-devel, Kent Yoder

Hi Kent,

Am Mittwoch, 5. Dezember 2012, 22:00:48 schrieb Kent Yoder:
>   This is already at least v3 of the driver IIRC. And its not fully
> committed at all, its just in a staging tree. I can blow it away at any
> time if we find problems.
> 
>   Not a problem. usually I'd attach any updates I planned to commit for
> public review, then if anything wasn't made public before I issue my
> pull request to send them to security-next, I'd append the full diff to
> the pull request at that time. Either way, all changes will hit a list
> at some point in time.
Ok - great ;) maybe my I got the 'planning on pushing'  wrong.


> > I thought the Mathias has changed the naming of the files? I don't see
> > that in your commit.
> 
>   Good catch, this is the kind of review I was asking for. :-)

Hehe. Glad to hear.
You know I care for the tpm subsystem ;)

> 
> > The version you committed to that branch still has some of the items of
> > my first review. (e.g.
> > 
> >  * 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.)
> > 
> > -> The (possible) GPL v3 clause has to go away for the kernel, but I'm
> > not a lawyer.
> 
>   A GPLv3 clause would say "v3 or any later version". This should be
> fine.

Hmm, okay. 
I just googled for it on lkml, there are some files and drivers.
So I guess it's okay - sorry for the noise.
But I'm not a lawyer, personally I'd go for GPLv2 only but that's my personal 
opinion. 


Thanks,
Peter



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

* Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-12-05 21:14                       ` Peter Hüwe
@ 2012-12-05 23:09                         ` Kent Yoder
  2012-12-06  0:10                           ` Peter Hüwe
  2012-12-06  0:20                           ` [PATCH] char/tpm: Use struct dev_pm_ops for power management Peter Huewe
  0 siblings, 2 replies; 33+ messages in thread
From: Kent Yoder @ 2012-12-05 23:09 UTC (permalink / raw)
  To: Peter Hüwe
  Cc: Mathias LEBLANC, Jean-Luc BLANC, Sirrix, linux-kernel,
	Rajiv Andrade, tpmdd-devel, Kent Yoder

On Wed, Dec 05, 2012 at 10:14:48PM +0100, Peter Hüwe wrote:
> Hi Kent, Matthias,
> 
> Am Mittwoch, 5. Dezember 2012, 19:07:20 schrieb Kent Yoder:
> >   Heh, duh, well of course it is. I've now staged everything I'm
> > planning on pushing at:
> > 
> > git://github.com/shpedoikal/linux.git tpmdd-12-05-12
> > 
> > Please test and let me know if I missed anything.
> 
> 
> I just checked out your commit from github.
> 
> Here's a part of the review:
> 
> Smatch still complains a bit, sparse is fine.:
> 
>  make -C /data/data-old/linux-2.6/ M=`pwd` C=1 CHECK=smatch modules
> make: Entering directory `/data/data-old/linux-2.6'
>   CHECK   /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:535 tpm_stm_i2c_recv() warn: variable dereferenced before check 'chip' (see line 531)
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:748 tpm_st33_i2c_probe() warn: variable dereferenced before check 'platform_data' (see line 659)
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:848 tpm_st33_i2c_pm_resume() warn: should this be a bitwise op?
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.c:848 tpm_st33_i2c_pm_resume() warn: should this be a bitwise op?
>   CC [M]  /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.o
>   Building modules, stage 2.
>   MODPOST 6 modules
>   LD [M]  /data/data-old/linux-2.6/drivers/char/tpm/tpm_stm_st33_i2c.ko
> make: Leaving directory `/data/data-old/linux-2.6'
> 
> Please check.
> 
> 
> (maybe also fix the checkpatch -strict stuff as well? Would be nice ;)
> 
> 
> 
> 
> 
> drivers/char/tpm/tpm_stm_st33_i2c.h 
> - Does the driver really need a seperate headerfile in drivers/char/tpm/ ? for me it seems everything can be included into the c-file.
> 
> > struct st_tpm_hash {
> >	int size;
> >	u8 *data;
> > };
> is unused - please remove.
> 
> > #define MINOR_NUM_I2C		224
> Please remove, it's unused and if you really need it use the one from tpm.h
> 
> include/linux/i2c/tpm_stm_st33_i2c.h
> I'm not sure if this is needed publicly? Or does only your driver need this?
> 
> >struct st33zp24_platform_data {
> Telling from the name I have no idea what this device is.
> 
> 
> 
> 
> 
> drivers/char/tpm/tpm_stm_st33_i2c.c
> 
> >enum stm33zp24_int_flags {
> >	TPM_GLOBAL_INT_ENABLE = 0x80,
> >	TPM_INTF_CMD_READY_INT = 0x080,
> >	TPM_INTF_FIFO_AVALAIBLE_INT = 0x040,
> >	TPM_INTF_WAKE_UP_READY_INT = 0x020,
> >	TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
> >	TPM_INTF_STS_VALID_INT = 0x002,
> >	TPM_INTF_DATA_AVAIL_INT = 0x001,
> >};
> 
> Why the leading zeros? please remove.
> 
> 
> > static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
> >...
> > static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
> >,,,
> >static struct i2c_driver tpm_st33_i2c_driver = {
> >	.driver = {
> >		   .owner = THIS_MODULE,
> >		   .name = TPM_ST33_I2C,
> >		   },
> >	.probe = tpm_st33_i2c_probe,
> >	.remove = tpm_st33_i2c_remove,
> >	.resume = tpm_st33_i2c_pm_resume,
> >	.suspend = tpm_st33_i2c_pm_suspend,
> >	.id_table = tpm_st33_i2c_id
> >};
> 
> Please convert resume/suspend  to .driver.pm 
> 
> It's pretty easy.
> See this post  for details
> http://sourceforge.net/mailarchive/message.php?msg_id=29516784
> Rafael did spent quite a lot of effort to convert almost every driver back then, so we should 'fix' new ones.

Not sure how easy this will be considering these routines are
i2c-specific -- they don't just call the tpm_tpm_* functions like the
other drivers.

Anyway, I left this off but I believe I've fixed up the other major
issues. We can leave the more nit-picky stuff for another day.

Please test:

git://github.com/shpedoikal/linux.git tpmdd-12-06-12

Kent

> 
> 
> > /*
> >  * tpm_st33_i2c_init initialize driver
> >  * @return: 0 if successful, else non zero value.
> >  */
> > static int __init tpm_st33_i2c_init(void)
> > {
> > 	return i2c_add_driver(&tpm_st33_i2c_driver);
> > }
> > 
> > /*
> >  * tpm_st33_i2c_exit The kernel calls this function during unloading the
> >  * module or during shut down process
> >  */
> > static void __exit tpm_st33_i2c_exit(void)
> > {
> > 	i2c_del_driver(&tpm_st33_i2c_driver);
> > }
> > 
> > module_init(tpm_st33_i2c_init);
> > module_exit(tpm_st33_i2c_exit);
> 
> Hooray for oneliners ;)
> + module_i2c_driver(tpm_st33_i2c_driver);
> 
> 
> 
> Keep on hacking ;)
> 
> Thanks,
> PeterH
> 
> 


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

* Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-12-05 23:09                         ` Kent Yoder
@ 2012-12-06  0:10                           ` Peter Hüwe
  2012-12-06 15:06                             ` Kent Yoder
  2012-12-06  0:20                           ` [PATCH] char/tpm: Use struct dev_pm_ops for power management Peter Huewe
  1 sibling, 1 reply; 33+ messages in thread
From: Peter Hüwe @ 2012-12-06  0:10 UTC (permalink / raw)
  To: Kent Yoder
  Cc: Mathias LEBLANC, Jean-Luc BLANC, Sirrix, linux-kernel,
	Rajiv Andrade, tpmdd-devel, Kent Yoder

Am Donnerstag, 6. Dezember 2012, 00:09:41 schrieb Kent Yoder:
> > 
> > > static int tpm_st33_i2c_pm_suspend(struct i2c_client *client,
> > > pm_message_t mesg)
> > >
> > >...
> > >
> > > static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
> > >
> > >,,,
> > >static struct i2c_driver tpm_st33_i2c_driver = {
> > >
> > >	.driver = {
> > >	
> > >		   .owner = THIS_MODULE,
> > >		   .name = TPM_ST33_I2C,
> > >		   },
> > >	
> > >	.probe = tpm_st33_i2c_probe,
> > >	.remove = tpm_st33_i2c_remove,
> > >	.resume = tpm_st33_i2c_pm_resume,
> > >	.suspend = tpm_st33_i2c_pm_suspend,
> > >	.id_table = tpm_st33_i2c_id
> > >
> > >};
> > 
> > Please convert resume/suspend  to .driver.pm
> > 
> > It's pretty easy.
> > See this post  for details
> > http://sourceforge.net/mailarchive/message.php?msg_id=29516784
> > Rafael did spent quite a lot of effort to convert almost every driver
> > back then, so we should 'fix' new ones.
> 
> Not sure how easy this will be considering these routines are
> i2c-specific -- they don't just call the tpm_tpm_* functions like the
> other drivers.

Why are they really i2c-specific?
The only i2c specific part is the i2c_get_clientdata - which calls 
get_dev_drvdata internally.
And I since we already get the correct struct device we don't need to use 
TPM_VPRIV in order to access the platform data. 

I'll send a patch - see next email.
@Matthias: can you please test this? As I cannot do this.


Thanks,
Peter



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

* [PATCH] char/tpm: Use struct dev_pm_ops for power management
  2012-12-05 23:09                         ` Kent Yoder
  2012-12-06  0:10                           ` Peter Hüwe
@ 2012-12-06  0:20                           ` Peter Huewe
  2012-12-06 15:07                             ` Kent Yoder
  2012-12-06 16:27                             ` Kent Yoder
  1 sibling, 2 replies; 33+ messages in thread
From: Peter Huewe @ 2012-12-06  0:20 UTC (permalink / raw)
  To: Kent Yoder
  Cc: Peter Huewe, Mathias LEBLANC, Jean-Luc BLANC, Sirrix,
	linux-kernel, Rajiv Andrade, tpmdd-devel, Kent Yoder,
	Peter Huewe

This patch converts the suspend and resume functions for
tpm_i2c_stm_st33 to the new dev_pm_ops.

Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
---
Note:
I'm sending this patch on behalf of myself only and nobody else, 
especially not my employer - and I'm doing this in my spare time.
I have to inform you that I'm working for a direct competitor of the driver author,
but I'm not using any knowledge that is considered secret in any way.
I have a personal interest in the TPM subsystem and want to keep it as clean as possible.


 drivers/char/tpm/tpm_i2c_stm_st33.c |   25 ++++++++++---------------
 1 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.c b/drivers/char/tpm/tpm_i2c_stm_st33.c
index b11201f..ecbb81e 100644
--- a/drivers/char/tpm/tpm_i2c_stm_st33.c
+++ b/drivers/char/tpm/tpm_i2c_stm_st33.c
@@ -826,12 +826,10 @@ static __devexit int tpm_st33_i2c_remove(struct i2c_client *client)
  * @param: mesg, the power management message.
  * @return: 0 in case of success.
  */
-static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
+static int tpm_st33_i2c_pm_suspend(struct device *dev)
 {
-	struct tpm_chip *chip =
-	    (struct tpm_chip *)i2c_get_clientdata(client);
-	struct st33zp24_platform_data *pin_infos =
-		((struct i2c_client *)TPM_VPRIV(chip))->dev.platform_data;
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	struct st33zp24_platform_data *pin_infos = dev->platform_data;
 	int ret = 0;
 
 	if (power_mgt)
@@ -839,7 +837,7 @@ static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
 	else{
 		if (chip->data_buffer == NULL)
 			chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
-		ret = tpm_pm_suspend(&client->dev);
+		ret = tpm_pm_suspend(dev);
 	}
 	return ret;
 }				/* tpm_st33_i2c_suspend() */
@@ -849,12 +847,10 @@ static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
  * @param: client, the i2c_client drescription (TPM I2C description).
  * @return: 0 in case of success.
  */
-static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
+static int tpm_st33_i2c_pm_resume(struct device *dev)
 {
-	struct tpm_chip *chip =
-	    (struct tpm_chip *)i2c_get_clientdata(client);
-	struct st33zp24_platform_data *pin_infos =
-		((struct i2c_client *)TPM_VPRIV(chip))->dev.platform_data;
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	struct st33zp24_platform_data *pin_infos = dev->platform_data;
 
 	int ret = 0;
 
@@ -867,7 +863,7 @@ static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
 	} else{
 	if (chip->data_buffer == NULL)
 		chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
-	ret = tpm_pm_resume(&client->dev);
+	ret = tpm_pm_resume(dev);
 	if (!ret)
 		tpm_do_selftest(chip);
 	}
@@ -880,16 +876,15 @@ static const struct i2c_device_id tpm_st33_i2c_id[] = {
 };
 
 MODULE_DEVICE_TABLE(i2c, tpm_st33_i2c_id);
-
+static SIMPLE_DEV_PM_OPS(tpm_st33_i2c_ops, tpm_st33_i2c_pm_suspend, tpm_st33_i2c_pm_resume);
 static struct i2c_driver tpm_st33_i2c_driver = {
 	.driver = {
 		   .owner = THIS_MODULE,
 		   .name = TPM_ST33_I2C,
+		   .pm = &tpm_st33_i2c_ops,
 		   },
 	.probe = tpm_st33_i2c_probe,
 	.remove = tpm_st33_i2c_remove,
-	.resume = tpm_st33_i2c_pm_resume,
-	.suspend = tpm_st33_i2c_pm_suspend,
 	.id_table = tpm_st33_i2c_id
 };
 
-- 
1.7.8.6


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

* Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x
  2012-12-06  0:10                           ` Peter Hüwe
@ 2012-12-06 15:06                             ` Kent Yoder
  2012-12-08  4:00                               ` [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x OOPS! Peter Hüwe
  0 siblings, 1 reply; 33+ messages in thread
From: Kent Yoder @ 2012-12-06 15:06 UTC (permalink / raw)
  To: Peter Hüwe
  Cc: Mathias LEBLANC, Jean-Luc BLANC, Sirrix, linux-kernel,
	Rajiv Andrade, tpmdd-devel, Kent Yoder

On Thu, Dec 06, 2012 at 01:10:32AM +0100, Peter Hüwe wrote:
> Am Donnerstag, 6. Dezember 2012, 00:09:41 schrieb Kent Yoder:
> > > 
> > > > static int tpm_st33_i2c_pm_suspend(struct i2c_client *client,
> > > > pm_message_t mesg)
> > > >
> > > >...
> > > >
> > > > static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
> > > >
> > > >,,,
> > > >static struct i2c_driver tpm_st33_i2c_driver = {
> > > >
> > > >	.driver = {
> > > >	
> > > >		   .owner = THIS_MODULE,
> > > >		   .name = TPM_ST33_I2C,
> > > >		   },
> > > >	
> > > >	.probe = tpm_st33_i2c_probe,
> > > >	.remove = tpm_st33_i2c_remove,
> > > >	.resume = tpm_st33_i2c_pm_resume,
> > > >	.suspend = tpm_st33_i2c_pm_suspend,
> > > >	.id_table = tpm_st33_i2c_id
> > > >
> > > >};
> > > 
> > > Please convert resume/suspend  to .driver.pm
> > > 
> > > It's pretty easy.
> > > See this post  for details
> > > http://sourceforge.net/mailarchive/message.php?msg_id=29516784
> > > Rafael did spent quite a lot of effort to convert almost every driver
> > > back then, so we should 'fix' new ones.
> > 
> > Not sure how easy this will be considering these routines are
> > i2c-specific -- they don't just call the tpm_tpm_* functions like the
> > other drivers.
> 
> Why are they really i2c-specific?
> The only i2c specific part is the i2c_get_clientdata - which calls 
> get_dev_drvdata internally.
> And I since we already get the correct struct device we don't need to use 
> TPM_VPRIV in order to access the platform data. 

 I was referring to the power mgmt stuff. Those functions take struct
device, not a i2c_client *.

Kent

> I'll send a patch - see next email.
> @Matthias: can you please test this? As I cannot do this.
> 
> 
> Thanks,
> Peter
> 
> 


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

* Re: [PATCH] char/tpm: Use struct dev_pm_ops for power management
  2012-12-06  0:20                           ` [PATCH] char/tpm: Use struct dev_pm_ops for power management Peter Huewe
@ 2012-12-06 15:07                             ` Kent Yoder
  2012-12-10 18:11                               ` Mathias LEBLANC
  2012-12-06 16:27                             ` Kent Yoder
  1 sibling, 1 reply; 33+ messages in thread
From: Kent Yoder @ 2012-12-06 15:07 UTC (permalink / raw)
  To: Peter Huewe
  Cc: Mathias LEBLANC, Jean-Luc BLANC, Sirrix, linux-kernel,
	Rajiv Andrade, tpmdd-devel, Kent Yoder

On Thu, Dec 06, 2012 at 01:20:51AM +0100, Peter Huewe wrote:
> This patch converts the suspend and resume functions for
> tpm_i2c_stm_st33 to the new dev_pm_ops.

  Ignore my last mail. I'll take a look at this.

Thanks,
Kent

> Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
> ---
> Note:
> I'm sending this patch on behalf of myself only and nobody else, 
> especially not my employer - and I'm doing this in my spare time.
> I have to inform you that I'm working for a direct competitor of the driver author,
> but I'm not using any knowledge that is considered secret in any way.
> I have a personal interest in the TPM subsystem and want to keep it as clean as possible.
> 
> 
>  drivers/char/tpm/tpm_i2c_stm_st33.c |   25 ++++++++++---------------
>  1 files changed, 10 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.c b/drivers/char/tpm/tpm_i2c_stm_st33.c
> index b11201f..ecbb81e 100644
> --- a/drivers/char/tpm/tpm_i2c_stm_st33.c
> +++ b/drivers/char/tpm/tpm_i2c_stm_st33.c
> @@ -826,12 +826,10 @@ static __devexit int tpm_st33_i2c_remove(struct i2c_client *client)
>   * @param: mesg, the power management message.
>   * @return: 0 in case of success.
>   */
> -static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
> +static int tpm_st33_i2c_pm_suspend(struct device *dev)
>  {
> -	struct tpm_chip *chip =
> -	    (struct tpm_chip *)i2c_get_clientdata(client);
> -	struct st33zp24_platform_data *pin_infos =
> -		((struct i2c_client *)TPM_VPRIV(chip))->dev.platform_data;
> +	struct tpm_chip *chip = dev_get_drvdata(dev);
> +	struct st33zp24_platform_data *pin_infos = dev->platform_data;
>  	int ret = 0;
> 
>  	if (power_mgt)
> @@ -839,7 +837,7 @@ static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
>  	else{
>  		if (chip->data_buffer == NULL)
>  			chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
> -		ret = tpm_pm_suspend(&client->dev);
> +		ret = tpm_pm_suspend(dev);
>  	}
>  	return ret;
>  }				/* tpm_st33_i2c_suspend() */
> @@ -849,12 +847,10 @@ static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
>   * @param: client, the i2c_client drescription (TPM I2C description).
>   * @return: 0 in case of success.
>   */
> -static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
> +static int tpm_st33_i2c_pm_resume(struct device *dev)
>  {
> -	struct tpm_chip *chip =
> -	    (struct tpm_chip *)i2c_get_clientdata(client);
> -	struct st33zp24_platform_data *pin_infos =
> -		((struct i2c_client *)TPM_VPRIV(chip))->dev.platform_data;
> +	struct tpm_chip *chip = dev_get_drvdata(dev);
> +	struct st33zp24_platform_data *pin_infos = dev->platform_data;
> 
>  	int ret = 0;
> 
> @@ -867,7 +863,7 @@ static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
>  	} else{
>  	if (chip->data_buffer == NULL)
>  		chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
> -	ret = tpm_pm_resume(&client->dev);
> +	ret = tpm_pm_resume(dev);
>  	if (!ret)
>  		tpm_do_selftest(chip);
>  	}
> @@ -880,16 +876,15 @@ static const struct i2c_device_id tpm_st33_i2c_id[] = {
>  };
> 
>  MODULE_DEVICE_TABLE(i2c, tpm_st33_i2c_id);
> -
> +static SIMPLE_DEV_PM_OPS(tpm_st33_i2c_ops, tpm_st33_i2c_pm_suspend, tpm_st33_i2c_pm_resume);
>  static struct i2c_driver tpm_st33_i2c_driver = {
>  	.driver = {
>  		   .owner = THIS_MODULE,
>  		   .name = TPM_ST33_I2C,
> +		   .pm = &tpm_st33_i2c_ops,
>  		   },
>  	.probe = tpm_st33_i2c_probe,
>  	.remove = tpm_st33_i2c_remove,
> -	.resume = tpm_st33_i2c_pm_resume,
> -	.suspend = tpm_st33_i2c_pm_suspend,
>  	.id_table = tpm_st33_i2c_id
>  };
> 
> -- 
> 1.7.8.6
> 


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

* Re: [PATCH] char/tpm: Use struct dev_pm_ops for power management
  2012-12-06  0:20                           ` [PATCH] char/tpm: Use struct dev_pm_ops for power management Peter Huewe
  2012-12-06 15:07                             ` Kent Yoder
@ 2012-12-06 16:27                             ` Kent Yoder
  2012-12-08  3:55                               ` Peter Hüwe
  1 sibling, 1 reply; 33+ messages in thread
From: Kent Yoder @ 2012-12-06 16:27 UTC (permalink / raw)
  To: Peter Huewe
  Cc: Mathias LEBLANC, Jean-Luc BLANC, Sirrix, linux-kernel,
	Rajiv Andrade, tpmdd-devel, Kent Yoder

On Thu, Dec 06, 2012 at 01:20:51AM +0100, Peter Huewe wrote:
> This patch converts the suspend and resume functions for
> tpm_i2c_stm_st33 to the new dev_pm_ops.
> 
> Signed-off-by: Peter Huewe <peterhuewe@gmx.de>

  One minor tweak, the PM funcs need to be inside CONFIG_PM_SLEEP to
avoid warnings when compiled without PM support.  Applied with that
change only.

Thanks Peter!
Kent

> ---
> Note:
> I'm sending this patch on behalf of myself only and nobody else, 
> especially not my employer - and I'm doing this in my spare time.
> I have to inform you that I'm working for a direct competitor of the driver author,
> but I'm not using any knowledge that is considered secret in any way.
> I have a personal interest in the TPM subsystem and want to keep it as clean as possible.
> 
> 
>  drivers/char/tpm/tpm_i2c_stm_st33.c |   25 ++++++++++---------------
>  1 files changed, 10 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.c b/drivers/char/tpm/tpm_i2c_stm_st33.c
> index b11201f..ecbb81e 100644
> --- a/drivers/char/tpm/tpm_i2c_stm_st33.c
> +++ b/drivers/char/tpm/tpm_i2c_stm_st33.c
> @@ -826,12 +826,10 @@ static __devexit int tpm_st33_i2c_remove(struct i2c_client *client)
>   * @param: mesg, the power management message.
>   * @return: 0 in case of success.
>   */
> -static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
> +static int tpm_st33_i2c_pm_suspend(struct device *dev)
>  {
> -	struct tpm_chip *chip =
> -	    (struct tpm_chip *)i2c_get_clientdata(client);
> -	struct st33zp24_platform_data *pin_infos =
> -		((struct i2c_client *)TPM_VPRIV(chip))->dev.platform_data;
> +	struct tpm_chip *chip = dev_get_drvdata(dev);
> +	struct st33zp24_platform_data *pin_infos = dev->platform_data;
>  	int ret = 0;
> 
>  	if (power_mgt)
> @@ -839,7 +837,7 @@ static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
>  	else{
>  		if (chip->data_buffer == NULL)
>  			chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
> -		ret = tpm_pm_suspend(&client->dev);
> +		ret = tpm_pm_suspend(dev);
>  	}
>  	return ret;
>  }				/* tpm_st33_i2c_suspend() */
> @@ -849,12 +847,10 @@ static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
>   * @param: client, the i2c_client drescription (TPM I2C description).
>   * @return: 0 in case of success.
>   */
> -static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
> +static int tpm_st33_i2c_pm_resume(struct device *dev)
>  {
> -	struct tpm_chip *chip =
> -	    (struct tpm_chip *)i2c_get_clientdata(client);
> -	struct st33zp24_platform_data *pin_infos =
> -		((struct i2c_client *)TPM_VPRIV(chip))->dev.platform_data;
> +	struct tpm_chip *chip = dev_get_drvdata(dev);
> +	struct st33zp24_platform_data *pin_infos = dev->platform_data;
> 
>  	int ret = 0;
> 
> @@ -867,7 +863,7 @@ static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
>  	} else{
>  	if (chip->data_buffer == NULL)
>  		chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
> -	ret = tpm_pm_resume(&client->dev);
> +	ret = tpm_pm_resume(dev);
>  	if (!ret)
>  		tpm_do_selftest(chip);
>  	}
> @@ -880,16 +876,15 @@ static const struct i2c_device_id tpm_st33_i2c_id[] = {
>  };
> 
>  MODULE_DEVICE_TABLE(i2c, tpm_st33_i2c_id);
> -
> +static SIMPLE_DEV_PM_OPS(tpm_st33_i2c_ops, tpm_st33_i2c_pm_suspend, tpm_st33_i2c_pm_resume);
>  static struct i2c_driver tpm_st33_i2c_driver = {
>  	.driver = {
>  		   .owner = THIS_MODULE,
>  		   .name = TPM_ST33_I2C,
> +		   .pm = &tpm_st33_i2c_ops,
>  		   },
>  	.probe = tpm_st33_i2c_probe,
>  	.remove = tpm_st33_i2c_remove,
> -	.resume = tpm_st33_i2c_pm_resume,
> -	.suspend = tpm_st33_i2c_pm_suspend,
>  	.id_table = tpm_st33_i2c_id
>  };
> 
> -- 
> 1.7.8.6
> 


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

* Re: [PATCH] char/tpm: Use struct dev_pm_ops for power management
  2012-12-06 16:27                             ` Kent Yoder
@ 2012-12-08  3:55                               ` Peter Hüwe
  0 siblings, 0 replies; 33+ messages in thread
From: Peter Hüwe @ 2012-12-08  3:55 UTC (permalink / raw)
  To: Kent Yoder
  Cc: Mathias LEBLANC, Jean-Luc BLANC, Sirrix, linux-kernel,
	Rajiv Andrade, tpmdd-devel, Kent Yoder

Am Donnerstag, 6. Dezember 2012, 17:27:02 schrieb Kent Yoder:
> On Thu, Dec 06, 2012 at 01:20:51AM +0100, Peter Huewe wrote:
> > This patch converts the suspend and resume functions for
> > tpm_i2c_stm_st33 to the new dev_pm_ops.
> > 
> > Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
> 
>   One minor tweak, the PM funcs need to be inside CONFIG_PM_SLEEP to
> avoid warnings when compiled without PM support.  Applied with that
> change only.
> 
> Thanks Peter!
> Kent
Great to hear!

Peter

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

* Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x OOPS!
  2012-12-06 15:06                             ` Kent Yoder
@ 2012-12-08  4:00                               ` Peter Hüwe
       [not found]                                 ` <20130108172053.GA11223@ennui.austin.ibm.com>
  0 siblings, 1 reply; 33+ messages in thread
From: Peter Hüwe @ 2012-12-08  4:00 UTC (permalink / raw)
  To: Kent Yoder
  Cc: Mathias LEBLANC, Jean-Luc BLANC, Sirrix, linux-kernel,
	Rajiv Andrade, tpmdd-devel, Kent Yoder

Hi,

since I don't have a tpm I simply tried out whether the handling without a tpm 
is correct, which it unfortunately isn't as my kernel oopses.

Steps to reproduce:
# insmod  /data/data-old/linux-2.6/drivers/char/tpm/tpm_i2c_stm_st33.ko
# echo st33zp24_i2c 0x20 /sys/bus/i2c/devices/i2c-1/new_device 



BUG: unable to handle kernel NULL pointer dereference at 0000000000000018
IP: [<ffffffffa02ff4ad>] tpm_st33_i2c_probe+0x87/0x21a [tpm_i2c_stm_st33]
PGD 3dcbbe067 PUD 3e994b067 PMD 0
Oops: 0002 [#1] PREEMPT SMP
Modules linked in: tpm_i2c_stm_st33(O) tpm(O) tpm_bios(O) w83627ehf hwmon_vid 
ipv6 snd_hda_codec_hdmi snd_hda_codec_realtek joydev usbhid coretemp kvm_intel 
kvm ghash_clmulni_intel sg pcspkr snd_hda_intel snd_hda_codec snd_hwdep 
snd_pcm snd_timer snd i2c_i801 snd_page_alloc mei [last unloaded: 
tpm_i2c_stm_st33]
CPU 2
Pid: 4454, comm: bash Tainted: G        W  O 3.6.9 #14 To Be Filled By O.E.M. 
To Be Filled By O.E.M./Z77 Pro4
RIP: 0010:[<ffffffffa02ff4ad>]  [<ffffffffa02ff4ad>] tpm_st33_i2c_probe+0x87/0x21a 
[tpm_i2c_stm_st33]
RSP: 0018:ffff8803dcb87c18  EFLAGS: 00010286
RAX: ffff8803eb0d1800 RBX: ffff8803ff710400 RCX: 0000000000000000
RDX: 0000000000000000 RSI: ffff88041d0026d0 RDI: 0000000000000001
RBP: ffff8803dcb87c38 R08: 000000000000000b R09: 0000000000000001
R10: 0000000000000001 R11: ffff8803ff710400 R12: 0000000000000000
R13: ffff8803ff710c00 R14: ffff8803ff710c28 R15: ffff8803ff710c04
FS:  00007f520567a700(0000) GS:ffff88041f280000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000018 CR3: 00000003e48b0000 CR4: 00000000001407e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process bash (pid: 4454, threadinfo ffff8803dcb86000, task ffff8803c87226c0)
Stack:
 ffff8803ff710c28 ffffffffa02ffb80 ffffffffa02ff426 ffff8803ff710c00
 ffff8803dcb87c78 ffffffff8134079a ffffffffa02ffe00 ffff8803ff710c28
 00000000ffffffed ffffffffa02ffe00 0000000000000000 ffff88040ebe4460
Call Trace:
 [<ffffffffa02ff426>] ? request_locality+0xc2/0xc2 [tpm_i2c_stm_st33]
 [<ffffffff8134079a>] i2c_device_probe+0xa4/0xcd
 [<ffffffff812b9c24>] driver_probe_device+0xa9/0x1bf
 [<ffffffff812b9de9>] __device_attach+0x35/0x3a
 [<ffffffff812b9db4>] ? __driver_attach+0x7a/0x7a
 [<ffffffff812b84d7>] bus_for_each_drv+0x51/0x87
 [<ffffffff812b9b3f>] device_attach+0x6e/0x8e
 [<ffffffff812b91b0>] bus_probe_device+0x2d/0x98
 [<ffffffff812b7ace>] device_add+0x3e1/0x548
 [<ffffffff812bf2b3>] ? device_pm_init+0x60/0x84
 [<ffffffff812b7c4c>] device_register+0x17/0x1b
 [<ffffffff813410c4>] i2c_new_device+0x12b/0x175
 [<ffffffff813411e4>] i2c_sysfs_new_device+0xd6/0x15a
 [<ffffffff812b6394>] dev_attr_store+0x1b/0x1d
 [<ffffffff81136f39>] sysfs_write_file+0xef/0x12b
 [<ffffffff810e4ac3>] vfs_write+0xa9/0x119
 [<ffffffff810e4cfa>] sys_write+0x45/0x6c
 [<ffffffff814005a2>] system_call_fastpath+0x16/0x1b
Code: ff 48 c7 c6 a7 fa 2f a0 48 85 c0 48 89 c3 74 cd 48 8b 3d d7 d0 2a e1 be 
d0 00 00 00 4d 8b a5 c8 00 00 00 e8 3b 32 de e0 48 85 c0 <49> 89 44 24 18 0f 
84 5a 01 00 00 48 8b 3d b1 d0 2a e1 be d0 00
RIP  [<ffffffffa02ff4ad>] tpm_st33_i2c_probe+0x87/0x21a [tpm_i2c_stm_st33]
 RSP <ffff8803dcb87c18>
CR2: 0000000000000018
---[ end trace ddc5676681e8ed72 ]---




Thanks,
Peter

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

* RE: [PATCH] char/tpm: Use struct dev_pm_ops for power management
  2012-12-06 15:07                             ` Kent Yoder
@ 2012-12-10 18:11                               ` Mathias LEBLANC
  0 siblings, 0 replies; 33+ messages in thread
From: Mathias LEBLANC @ 2012-12-10 18:11 UTC (permalink / raw)
  To: Kent Yoder, Peter Huewe
  Cc: Jean-Luc BLANC, Sirrix, linux-kernel, Rajiv Andrade, tpmdd-devel,
	Kent Yoder

Hi Kent, Peter,

I am never in my office Thursday and Friday, I just saw your emails today.
I will transfer the tpm_i2c_stm_st33.h code to tpm_i2c_stm_st33.c
@Peter: I tested your patch and activate the CONFIG_PM_SLEEP in the kernel compilation.
Thanks Peter!

About:
"Not sure how easy this will be considering these routines are 
> > i2c-specific -- they don't just call the tpm_tpm_* functions like 
> > the other drivers."
We have created another function similar to the tpm_* functions, to ensure the good work of the tpm on each platform for each case.
But anyway , we use the tpm_* function in them.

Thanks,
Mathias Leblanc

-----Original Message-----
From: Kent Yoder [mailto:key@linux.vnet.ibm.com] 
Sent: 06 December, 2012 16:08
To: Peter Huewe
Cc: Mathias LEBLANC; Jean-Luc BLANC; Sirrix@jasper.es; linux-kernel@vger.kernel.org; Rajiv Andrade; tpmdd-devel@lists.sourceforge.net; Kent Yoder
Subject: Re: [PATCH] char/tpm: Use struct dev_pm_ops for power management

On Thu, Dec 06, 2012 at 01:20:51AM +0100, Peter Huewe wrote:
> This patch converts the suspend and resume functions for
> tpm_i2c_stm_st33 to the new dev_pm_ops.

  Ignore my last mail. I'll take a look at this.

Thanks,
Kent

> Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
> ---
> Note:
> I'm sending this patch on behalf of myself only and nobody else, 
> especially not my employer - and I'm doing this in my spare time.
> I have to inform you that I'm working for a direct competitor of the 
> driver author, but I'm not using any knowledge that is considered secret in any way.
> I have a personal interest in the TPM subsystem and want to keep it as clean as possible.
> 
> 
>  drivers/char/tpm/tpm_i2c_stm_st33.c |   25 ++++++++++---------------
>  1 files changed, 10 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.c 
> b/drivers/char/tpm/tpm_i2c_stm_st33.c
> index b11201f..ecbb81e 100644
> --- a/drivers/char/tpm/tpm_i2c_stm_st33.c
> +++ b/drivers/char/tpm/tpm_i2c_stm_st33.c
> @@ -826,12 +826,10 @@ static __devexit int tpm_st33_i2c_remove(struct i2c_client *client)
>   * @param: mesg, the power management message.
>   * @return: 0 in case of success.
>   */
> -static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, 
> pm_message_t mesg)
> +static int tpm_st33_i2c_pm_suspend(struct device *dev)
>  {
> -	struct tpm_chip *chip =
> -	    (struct tpm_chip *)i2c_get_clientdata(client);
> -	struct st33zp24_platform_data *pin_infos =
> -		((struct i2c_client *)TPM_VPRIV(chip))->dev.platform_data;
> +	struct tpm_chip *chip = dev_get_drvdata(dev);
> +	struct st33zp24_platform_data *pin_infos = dev->platform_data;
>  	int ret = 0;
> 
>  	if (power_mgt)
> @@ -839,7 +837,7 @@ static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
>  	else{
>  		if (chip->data_buffer == NULL)
>  			chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
> -		ret = tpm_pm_suspend(&client->dev);
> +		ret = tpm_pm_suspend(dev);
>  	}
>  	return ret;
>  }				/* tpm_st33_i2c_suspend() */
> @@ -849,12 +847,10 @@ static int tpm_st33_i2c_pm_suspend(struct i2c_client *client, pm_message_t mesg)
>   * @param: client, the i2c_client drescription (TPM I2C description).
>   * @return: 0 in case of success.
>   */
> -static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
> +static int tpm_st33_i2c_pm_resume(struct device *dev)
>  {
> -	struct tpm_chip *chip =
> -	    (struct tpm_chip *)i2c_get_clientdata(client);
> -	struct st33zp24_platform_data *pin_infos =
> -		((struct i2c_client *)TPM_VPRIV(chip))->dev.platform_data;
> +	struct tpm_chip *chip = dev_get_drvdata(dev);
> +	struct st33zp24_platform_data *pin_infos = dev->platform_data;
> 
>  	int ret = 0;
> 
> @@ -867,7 +863,7 @@ static int tpm_st33_i2c_pm_resume(struct i2c_client *client)
>  	} else{
>  	if (chip->data_buffer == NULL)
>  		chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
> -	ret = tpm_pm_resume(&client->dev);
> +	ret = tpm_pm_resume(dev);
>  	if (!ret)
>  		tpm_do_selftest(chip);
>  	}
> @@ -880,16 +876,15 @@ static const struct i2c_device_id 
> tpm_st33_i2c_id[] = {  };
> 
>  MODULE_DEVICE_TABLE(i2c, tpm_st33_i2c_id);
> -
> +static SIMPLE_DEV_PM_OPS(tpm_st33_i2c_ops, tpm_st33_i2c_pm_suspend, 
> +tpm_st33_i2c_pm_resume);
>  static struct i2c_driver tpm_st33_i2c_driver = {
>  	.driver = {
>  		   .owner = THIS_MODULE,
>  		   .name = TPM_ST33_I2C,
> +		   .pm = &tpm_st33_i2c_ops,
>  		   },
>  	.probe = tpm_st33_i2c_probe,
>  	.remove = tpm_st33_i2c_remove,
> -	.resume = tpm_st33_i2c_pm_resume,
> -	.suspend = tpm_st33_i2c_pm_suspend,
>  	.id_table = tpm_st33_i2c_id
>  };
> 
> --
> 1.7.8.6
> 


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

* RE: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x OOPS!
       [not found]                                 ` <20130108172053.GA11223@ennui.austin.ibm.com>
@ 2013-01-09 14:31                                   ` Mathias LEBLANC
  2013-01-09 19:41                                     ` Peter Hüwe
  0 siblings, 1 reply; 33+ messages in thread
From: Mathias LEBLANC @ 2013-01-09 14:31 UTC (permalink / raw)
  To: Kent Yoder
  Cc: Peter Hüwe, Jean-Luc BLANC, Sirrix, linux-kernel,
	tpmdd-devel, Kent Yoder

Hi Peter,

Do you have the I2C configuration activated ?
I have this error when I add the driver in a kernel with no I2C activated

-----Original Message-----
From: Kent Yoder [mailto:key@linux.vnet.ibm.com] 
Sent: 08 January, 2013 18:21
To: Mathias LEBLANC
Cc: Peter Hüwe; Jean-Luc BLANC; Sirrix@jasper.es; linux-kernel@vger.kernel.org; tpmdd-devel@lists.sourceforge.net; Kent Yoder
Subject: Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x OOPS!

On Sat, Dec 08, 2012 at 05:00:26AM +0100, Peter Hüwe wrote:
> Hi,
> 
> since I don't have a tpm I simply tried out whether the handling 
> without a tpm is correct, which it unfortunately isn't as my kernel oopses.
> 
> Steps to reproduce:
> # insmod  
> /data/data-old/linux-2.6/drivers/char/tpm/tpm_i2c_stm_st33.ko
> # echo st33zp24_i2c 0x20 /sys/bus/i2c/devices/i2c-1/new_device

  Mathias, can you address this oops?  We can't merge this driver until its resolved.

Kent

> 
> BUG: unable to handle kernel NULL pointer dereference at 
> 0000000000000018
> IP: [<ffffffffa02ff4ad>] tpm_st33_i2c_probe+0x87/0x21a 
> [tpm_i2c_stm_st33] PGD 3dcbbe067 PUD 3e994b067 PMD 0
> Oops: 0002 [#1] PREEMPT SMP
> Modules linked in: tpm_i2c_stm_st33(O) tpm(O) tpm_bios(O) w83627ehf 
> hwmon_vid
> ipv6 snd_hda_codec_hdmi snd_hda_codec_realtek joydev usbhid coretemp 
> kvm_intel kvm ghash_clmulni_intel sg pcspkr snd_hda_intel 
> snd_hda_codec snd_hwdep snd_pcm snd_timer snd i2c_i801 snd_page_alloc mei [last unloaded:
> tpm_i2c_stm_st33]
> CPU 2
> Pid: 4454, comm: bash Tainted: G        W  O 3.6.9 #14 To Be Filled By O.E.M. 
> To Be Filled By O.E.M./Z77 Pro4
> RIP: 0010:[<ffffffffa02ff4ad>]  [<ffffffffa02ff4ad>] 
> tpm_st33_i2c_probe+0x87/0x21a [tpm_i2c_stm_st33]
> RSP: 0018:ffff8803dcb87c18  EFLAGS: 00010286
> RAX: ffff8803eb0d1800 RBX: ffff8803ff710400 RCX: 0000000000000000
> RDX: 0000000000000000 RSI: ffff88041d0026d0 RDI: 0000000000000001
> RBP: ffff8803dcb87c38 R08: 000000000000000b R09: 0000000000000001
> R10: 0000000000000001 R11: ffff8803ff710400 R12: 0000000000000000
> R13: ffff8803ff710c00 R14: ffff8803ff710c28 R15: ffff8803ff710c04
> FS:  00007f520567a700(0000) GS:ffff88041f280000(0000) 
> knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 0000000000000018 CR3: 00000003e48b0000 CR4: 00000000001407e0
> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 
> Process bash (pid: 4454, threadinfo ffff8803dcb86000, task 
> ffff8803c87226c0)
> Stack:
>  ffff8803ff710c28 ffffffffa02ffb80 ffffffffa02ff426 ffff8803ff710c00
>  ffff8803dcb87c78 ffffffff8134079a ffffffffa02ffe00 ffff8803ff710c28  
> 00000000ffffffed ffffffffa02ffe00 0000000000000000 ffff88040ebe4460 
> Call Trace:
>  [<ffffffffa02ff426>] ? request_locality+0xc2/0xc2 [tpm_i2c_stm_st33]  
> [<ffffffff8134079a>] i2c_device_probe+0xa4/0xcd  [<ffffffff812b9c24>] 
> driver_probe_device+0xa9/0x1bf  [<ffffffff812b9de9>] 
> __device_attach+0x35/0x3a  [<ffffffff812b9db4>] ? 
> __driver_attach+0x7a/0x7a  [<ffffffff812b84d7>] 
> bus_for_each_drv+0x51/0x87  [<ffffffff812b9b3f>] 
> device_attach+0x6e/0x8e  [<ffffffff812b91b0>] 
> bus_probe_device+0x2d/0x98  [<ffffffff812b7ace>] 
> device_add+0x3e1/0x548  [<ffffffff812bf2b3>] ? 
> device_pm_init+0x60/0x84  [<ffffffff812b7c4c>] 
> device_register+0x17/0x1b  [<ffffffff813410c4>] 
> i2c_new_device+0x12b/0x175  [<ffffffff813411e4>] 
> i2c_sysfs_new_device+0xd6/0x15a  [<ffffffff812b6394>] 
> dev_attr_store+0x1b/0x1d  [<ffffffff81136f39>] 
> sysfs_write_file+0xef/0x12b  [<ffffffff810e4ac3>] vfs_write+0xa9/0x119  
> [<ffffffff810e4cfa>] sys_write+0x45/0x6c  [<ffffffff814005a2>] 
> system_call_fastpath+0x16/0x1b
> Code: ff 48 c7 c6 a7 fa 2f a0 48 85 c0 48 89 c3 74 cd 48 8b 3d d7 d0 
> 2a e1 be
> d0 00 00 00 4d 8b a5 c8 00 00 00 e8 3b 32 de e0 48 85 c0 <49> 89 44 24 
> 18 0f
> 84 5a 01 00 00 48 8b 3d b1 d0 2a e1 be d0 00 RIP  [<ffffffffa02ff4ad>] 
> tpm_st33_i2c_probe+0x87/0x21a [tpm_i2c_stm_st33]  RSP 
> <ffff8803dcb87c18>
> CR2: 0000000000000018
> ---[ end trace ddc5676681e8ed72 ]---
> 
> 
> 
> 
> Thanks,
> Peter
> 

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

* Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x OOPS!
  2013-01-09 14:31                                   ` Mathias LEBLANC
@ 2013-01-09 19:41                                     ` Peter Hüwe
  2013-01-22 23:30                                       ` Kent Yoder
  0 siblings, 1 reply; 33+ messages in thread
From: Peter Hüwe @ 2013-01-09 19:41 UTC (permalink / raw)
  To: tpmdd-devel
  Cc: Mathias LEBLANC, Kent Yoder, Jean-Luc BLANC, Sirrix,
	linux-kernel, Kent Yoder

Hi,

> Do you have the I2C configuration activated ?
> I have this error when I add the driver in a kernel with no I2C activated

I2C works fine on my beaglebone, however  I did not add the platform data to my 
boardfile.
a) as I don't use board files anymore but device trees ;)
b) it's perfectly legit to load a driver without the platform data and probe 
it at runtime (which then in doubt fails to probe).

In my opinion a driver should never ever oops, even if the user does something 
stupid (e.g. like probing from userspace ;)

The fix is as simple as adding a simple 
if (!platform_data) return -ENODEV;
or something similar.

Thanks,
Peter


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

* Re: [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x OOPS!
  2013-01-09 19:41                                     ` Peter Hüwe
@ 2013-01-22 23:30                                       ` Kent Yoder
  0 siblings, 0 replies; 33+ messages in thread
From: Kent Yoder @ 2013-01-22 23:30 UTC (permalink / raw)
  To: Peter Hüwe
  Cc: tpmdd-devel, Mathias LEBLANC, Kent Yoder, Jean-Luc BLANC, Sirrix,
	linux-kernel

On Wed, Jan 9, 2013 at 1:41 PM, Peter Hüwe <PeterHuewe@gmx.de> wrote:
> In my opinion a driver should never ever oops, even if the user does something
> stupid (e.g. like probing from userspace ;)

  Exactly...  I've coded up a fix for the oops and staged it here, please test:

https://github.com/shpedoikal/linux.git tpmdd-01-22-13

Thanks,
Kent

> The fix is as simple as adding a simple
> if (!platform_data) return -ENODEV;
> or something similar.
>
> Thanks,
> Peter
>

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

* RE: [PATCH] char/tpm: Use struct dev_pm_ops for power management.
  2012-08-06 19:29   ` Kent Yoder
@ 2012-08-07  7:30     ` Peter.Huewe
  0 siblings, 0 replies; 33+ messages in thread
From: Peter.Huewe @ 2012-08-07  7:30 UTC (permalink / raw)
  To: key
  Cc: jmorris, linux-kernel, linux-security-module, tpmdd-devel,
	bfreed, safford, hpa

Hi Kent,

> Thanks Peter. One more request - can you roll this fix into the driver
> patch itself and just add a note in the change log?  Sorry I didn't
> mention this before.

Yes I'll do that.
And while at it I'll also replace our i2c_transfer_nolock with the new (in 3.6rc-1) __i2c_transfer function and 
integrate Bryans Patch directly into the driver.

Peter



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

* Re: [PATCH] char/tpm: Use struct dev_pm_ops for power management.
  2012-08-06  7:58 ` [PATCH] char/tpm: Use struct dev_pm_ops for power management Peter Huewe
@ 2012-08-06 19:29   ` Kent Yoder
  2012-08-07  7:30     ` Peter.Huewe
  0 siblings, 1 reply; 33+ messages in thread
From: Kent Yoder @ 2012-08-06 19:29 UTC (permalink / raw)
  To: Peter Huewe
  Cc: jmorris, linux-kernel, linux-security-module, tpmdd-devel,
	Bryan Freed, David Safford, hpa

On Mon, Aug 06, 2012 at 09:58:59AM +0200, Peter Huewe wrote:
> Make the tpm_i2c_infineon driver define its PM callbacks trough a
> struct dev_pm_ops by using SIMPLE_DEV_PM_OPS instead of coding it
> explicitly.
> 
> This simplifies the code and allows the driver to use tpm_pm_suspend()
> and tpm_pm_resume() as its PM callbacks directly, without defining its
> own PM callback routines.

  Thanks Peter. One more request - can you roll this fix into the driver
patch itself and just add a note in the change log?  Sorry I didn't
mention this before.

Thanks,
Kent

> Signed-off-by: Peter Huewe <peter.huewe@infineon.com>
> ---
> Thanks Kent and Rafael - much better this way ;)
> 
>  drivers/char/tpm/tpm_i2c_infineon.c |   30 +-----------------------------
>  1 files changed, 1 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
> index 1794a09..65761b6 100644
> --- a/drivers/char/tpm/tpm_i2c_infineon.c
> +++ b/drivers/char/tpm/tpm_i2c_infineon.c
> @@ -655,35 +655,7 @@ static const struct i2c_device_id tpm_tis_i2c_table[] = {
>  };
> 
>  MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table);
> -
> -#ifdef CONFIG_PM
> -/* NOTE:
> - * Suspend does currently not work Nvidias Tegra2 Platform
> - * but works fine on Beagleboard (arm omap).
> - *
> - * This function will block System Suspend if TPM is not initialized,
> - * however the TPM is usually initialized by BIOS/u-boot or by sending
> - * a TPM_Startup command.
> - */
> -static int tpm_tis_i2c_suspend(struct device *dev)
> -{
> -	return tpm_pm_suspend(dev, dev->power.power_state);
> -}
> -
> -static int tpm_tis_i2c_resume(struct device *dev)
> -{
> -	return tpm_pm_resume(dev);
> -}
> -
> -static const struct dev_pm_ops tpm_tis_i2c_ops = {
> -	.suspend = tpm_tis_i2c_suspend,
> -	.resume = tpm_tis_i2c_resume,
> -};
> -#else
> -#define tpm_tis_i2c_suspend NULL
> -#define tpm_tis_i2c_resume NULL
> -#define tpm_tis_i2c_ops NULL
> -#endif
> +static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume);
> 
>  static int __devinit tpm_tis_i2c_probe(struct i2c_client *client,
>  			     const struct i2c_device_id *id)
> -- 
> 1.7.6.msysgit.0
> 


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

* [PATCH] char/tpm: Use struct dev_pm_ops for power management.
  2012-08-03 20:38 [PATCH] char/tpm: Fix compile error if CONFIG_PM is not set in tpm_i2c_infineon Kent Yoder
@ 2012-08-06  7:58 ` Peter Huewe
  2012-08-06 19:29   ` Kent Yoder
  0 siblings, 1 reply; 33+ messages in thread
From: Peter Huewe @ 2012-08-06  7:58 UTC (permalink / raw)
  To: Kent Yoder, jmorris
  Cc: linux-kernel, linux-security-module, tpmdd-devel, Bryan Freed,
	David Safford, hpa, Peter Huewe

Make the tpm_i2c_infineon driver define its PM callbacks trough a
struct dev_pm_ops by using SIMPLE_DEV_PM_OPS instead of coding it
explicitly.

This simplifies the code and allows the driver to use tpm_pm_suspend()
and tpm_pm_resume() as its PM callbacks directly, without defining its
own PM callback routines.

Signed-off-by: Peter Huewe <peter.huewe@infineon.com>
---
Thanks Kent and Rafael - much better this way ;)

 drivers/char/tpm/tpm_i2c_infineon.c |   30 +-----------------------------
 1 files changed, 1 insertions(+), 29 deletions(-)

diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
index 1794a09..65761b6 100644
--- a/drivers/char/tpm/tpm_i2c_infineon.c
+++ b/drivers/char/tpm/tpm_i2c_infineon.c
@@ -655,35 +655,7 @@ static const struct i2c_device_id tpm_tis_i2c_table[] = {
 };
 
 MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table);
-
-#ifdef CONFIG_PM
-/* NOTE:
- * Suspend does currently not work Nvidias Tegra2 Platform
- * but works fine on Beagleboard (arm omap).
- *
- * This function will block System Suspend if TPM is not initialized,
- * however the TPM is usually initialized by BIOS/u-boot or by sending
- * a TPM_Startup command.
- */
-static int tpm_tis_i2c_suspend(struct device *dev)
-{
-	return tpm_pm_suspend(dev, dev->power.power_state);
-}
-
-static int tpm_tis_i2c_resume(struct device *dev)
-{
-	return tpm_pm_resume(dev);
-}
-
-static const struct dev_pm_ops tpm_tis_i2c_ops = {
-	.suspend = tpm_tis_i2c_suspend,
-	.resume = tpm_tis_i2c_resume,
-};
-#else
-#define tpm_tis_i2c_suspend NULL
-#define tpm_tis_i2c_resume NULL
-#define tpm_tis_i2c_ops NULL
-#endif
+static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume);
 
 static int __devinit tpm_tis_i2c_probe(struct i2c_client *client,
 			     const struct i2c_device_id *id)
-- 
1.7.6.msysgit.0


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

end of thread, other threads:[~2013-01-22 23:30 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-19 22:15 [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x Mathias Leblanc
2012-11-19 22:15 ` [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 2.6 Mathias Leblanc
2012-11-26 17:46 ` [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x Kent Yoder
2012-11-27  8:44   ` Mathias LEBLANC
2012-11-27 14:48     ` [tpmdd-devel] " Kent Yoder
2012-11-28  8:54       ` Mathias LEBLANC
2012-11-28 15:31         ` Kent Yoder
2012-11-28 17:48           ` Mathias LEBLANC
2012-11-28 19:04             ` Kent Yoder
2012-11-29  0:04             ` Peter Hüwe
2012-12-05 16:11               ` Mathias LEBLANC
2012-12-05 17:13                 ` Kent Yoder
2012-12-05 17:45                   ` Kent Yoder
2012-12-05 18:07                     ` Kent Yoder
2012-12-05 20:20                       ` Peter Hüwe
2012-12-05 21:00                         ` Kent Yoder
2012-12-05 21:39                           ` Peter Hüwe
2012-12-05 21:14                       ` Peter Hüwe
2012-12-05 23:09                         ` Kent Yoder
2012-12-06  0:10                           ` Peter Hüwe
2012-12-06 15:06                             ` Kent Yoder
2012-12-08  4:00                               ` [tpmdd-devel] [PATCH 1/1] TPM: STMicroelectronics ST33 I2C KERNEL 3.x.x OOPS! Peter Hüwe
     [not found]                                 ` <20130108172053.GA11223@ennui.austin.ibm.com>
2013-01-09 14:31                                   ` Mathias LEBLANC
2013-01-09 19:41                                     ` Peter Hüwe
2013-01-22 23:30                                       ` Kent Yoder
2012-12-06  0:20                           ` [PATCH] char/tpm: Use struct dev_pm_ops for power management Peter Huewe
2012-12-06 15:07                             ` Kent Yoder
2012-12-10 18:11                               ` Mathias LEBLANC
2012-12-06 16:27                             ` Kent Yoder
2012-12-08  3:55                               ` Peter Hüwe
  -- strict thread matches above, loose matches on Subject: below --
2012-08-03 20:38 [PATCH] char/tpm: Fix compile error if CONFIG_PM is not set in tpm_i2c_infineon Kent Yoder
2012-08-06  7:58 ` [PATCH] char/tpm: Use struct dev_pm_ops for power management Peter Huewe
2012-08-06 19:29   ` Kent Yoder
2012-08-07  7:30     ` Peter.Huewe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).