static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
{
	struct tpm_nsc_priv *priv = dev_get_drvdata(&chip->dev);
	u8 *buffer = buf;
	u8 data, *p;
	u32 size;
	__be32 *native_size;

	if (count < 6)
		return -EIO;

	if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) {
		dev_err(&chip->dev, "F0 timeout\n");
		return -EIO;
	}

	data = inb(priv->base + NSC_DATA);
	if (data != NSC_COMMAND_NORMAL) {
		dev_err(&chip->dev, "not in normal mode (0x%x)\n",
			data);
		return -EIO;
	}

	/* read the whole packet */
	for (p = buffer; p < &buffer[count]; p++) {
		if (wait_for_stat
		    (chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) {
			dev_err(&chip->dev,
				"OBF timeout (while reading data)\n");
			return -EIO;
		}
		if (data & NSC_STATUS_F0)
			break;
		*p = inb(priv->base + NSC_DATA);
	}

	if ((data & NSC_STATUS_F0) == 0 &&
	(wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) {
		dev_err(&chip->dev, "F0 not set\n");
		return -EIO;
	}

	data = inb(priv->base + NSC_DATA);
	if (data != NSC_COMMAND_EOC) {
		dev_err(&chip->dev,
			"expected end of command(0x%x)\n", data);
		return -EIO;
	}

	native_size = (__force __be32 *) (buf + 2);
	size = be32_to_cpu(*native_size);

	if (count < size)
		return -EIO;

	return size;
}
/*
 * 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, ret;
	struct i2c_client *client;

	client = (struct i2c_client *)TPM_VPRIV(chip);

	while (size < count &&
	       wait_for_stat(chip,
			     TPM_STS_DATA_AVAIL | TPM_STS_VALID,
			     chip->vendor.timeout_c,
			     &chip->vendor.read_queue)
	       == 0) {
		burstcnt = get_burstcount(chip);
		if (burstcnt < 0)
			return burstcnt;
		len = min_t(int, burstcnt, count - size);
		ret = I2C_READ_DATA(client, TPM_DATA_FIFO, buf + size, len);
		if (ret < 0)
			return ret;

		size += len;
	}
	return size;
}
static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
{
	struct tpm_nsc_priv *priv = dev_get_drvdata(&chip->dev);
	u8 data;
	int i;

	/*
	 * If we hit the chip with back to back commands it locks up
	 * and never set IBF. Hitting it with this "hammer" seems to
	 * fix it. Not sure why this is needed, we followed the flow
	 * chart in the manual to the letter.
	 */
	outb(NSC_COMMAND_CANCEL, priv->base + NSC_COMMAND);

	if (nsc_wait_for_ready(chip) != 0)
		return -EIO;

	if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
		dev_err(&chip->dev, "IBF timeout\n");
		return -EIO;
	}

	outb(NSC_COMMAND_NORMAL, priv->base + NSC_COMMAND);
	if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
		dev_err(&chip->dev, "IBR timeout\n");
		return -EIO;
	}

	for (i = 0; i < count; i++) {
		if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
			dev_err(&chip->dev,
				"IBF timeout (while writing data)\n");
			return -EIO;
		}
		outb(buf[i], priv->base + NSC_DATA);
	}

	if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
		dev_err(&chip->dev, "IBF timeout\n");
		return -EIO;
	}
	outb(NSC_COMMAND_EOC, priv->base + NSC_COMMAND);

	return count;
}
Exemple #4
0
static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{
	int size = 0;
	int expected, status;

	if (count < TPM_HEADER_SIZE) {
		size = -EIO;
		goto out;
	}

	/* read first 10 bytes, including tag, paramsize, and result */
	size = recv_data(chip, buf, TPM_HEADER_SIZE);
	if (size < TPM_HEADER_SIZE) {
		dev_err(chip->dev, "Unable to read header\n");
		goto out;
	}

	expected = be32_to_cpu(*(__be32 *)(buf + 2));
	if ((size_t) expected > count) {
		size = -EIO;
		goto out;
	}

	size += recv_data(chip, &buf[TPM_HEADER_SIZE],
			  expected - TPM_HEADER_SIZE);
	if (size < expected) {
		dev_err(chip->dev, "Unable to read remainder of result\n");
		size = -ETIME;
		goto out;
	}

	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
	if (status & TPM_STS_DATA_AVAIL) {	/* retry? */
		dev_err(chip->dev, "Error left over data\n");
		size = -EIO;
		goto out;
	}

out:
	tpm_tis_i2c_ready(chip);
	/* The TPM needs some time to clean up here,
	 * so we sleep rather than keeping the bus busy
	 */
	usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI);
	release_locality(chip, chip->vendor.locality, 0);
	return size;
}
Exemple #5
0
static int recv_data(struct tpm_chip* tpm, uint8_t* buf, size_t count) {
   int size = 0;
   int burstcnt;
   while( size < count &&
	 wait_for_stat(tpm,
	    TPM_STS_DATA_AVAIL | TPM_STS_VALID,
	    tpm->timeout_c,
	    &tpm->read_queue)
	 == 0) {
      burstcnt = get_burstcount(tpm);
      for(; burstcnt > 0 && size < count; --burstcnt)
      {
	 buf[size++] = ioread8(TPM_DATA_FIFO(tpm, tpm->locality));
      }
   }
   return size;
}
Exemple #6
0
/*
 * st33zp24_pm_resume resume the TPM device
 * @param: tpm_data, the tpm phy.
 * @return: 0 in case of success.
 */
int st33zp24_pm_resume(struct device *dev)
{
	struct tpm_chip *chip = dev_get_drvdata(dev);
	struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
	int ret = 0;

	if (gpio_is_valid(tpm_dev->io_lpcpd)) {
		gpio_set_value(tpm_dev->io_lpcpd, 1);
		ret = wait_for_stat(chip,
				TPM_STS_VALID, chip->timeout_b,
				&tpm_dev->read_queue, false);
	} else {
		ret = tpm_pm_resume(dev);
		if (!ret)
			tpm_do_selftest(chip);
	}
	return ret;
} /* st33zp24_pm_resume() */
Exemple #7
0
/*
 * tpm_stm_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_stm_i2c_pm_resume(struct device *dev)
{
	struct tpm_chip *chip = dev_get_drvdata(dev);
	struct st33zp24_platform_data *pin_infos = dev->platform_data;

	int ret = 0;

	if (gpio_is_valid(pin_infos->io_lpcpd)) {
		gpio_set_value(pin_infos->io_lpcpd, 1);
		ret = wait_for_stat(chip,
				TPM_STS_VALID, chip->vendor.timeout_b,
				&chip->vendor.read_queue, false);
	} else {
		ret = tpm_pm_resume(dev);
		if (!ret)
			tpm_do_selftest(chip);
	}
	return ret;
} /* tpm_stm_i2c_pm_resume() */
Exemple #8
0
int tpm_tis_recv(struct tpm_chip* tpm, uint8_t* buf, size_t count) {
   int size = 0;
   int expected, status;

   if (count < TPM_HEADER_SIZE) {
      size = -EIO;
      goto out;
   }

   /* read first 10 bytes, including tag, paramsize, and result */
   if((size =
	    recv_data(tpm, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) {
      printk("Error reading tpm cmd header\n");
      goto out;
   }

   expected = be32_to_cpu(*((uint32_t*)(buf + 2)));
   if(expected > count) {
      size = -EIO;
      goto out;
   }

   if((size += recv_data(tpm, & buf[TPM_HEADER_SIZE],
	       expected - TPM_HEADER_SIZE)) < expected) {
      printk("Unable to read rest of tpm command size=%d expected=%d\n", size, expected);
      size = -ETIME;
      goto out;
   }

   wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c, &tpm->int_queue);
   status = tpm_tis_status(tpm);
   if(status & TPM_STS_DATA_AVAIL) {
      printk("Error: left over data\n");
      size = -EIO;
      goto out;
   }

out:
   tpm_tis_ready(tpm);
   release_locality(tpm, tpm->locality, 0);
   return size;
}
Exemple #9
0
/*
 * 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)
{
	struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
	int size = 0, burstcnt, len, ret;

	while (size < count &&
	       wait_for_stat(chip,
			     TPM_STS_DATA_AVAIL | TPM_STS_VALID,
			     chip->timeout_c,
			     &tpm_dev->read_queue, true) == 0) {
		burstcnt = get_burstcount(chip);
		if (burstcnt < 0)
			return burstcnt;
		len = min_t(int, burstcnt, count - size);
		ret = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_DATA_FIFO,
					 buf + size, len);
		if (ret < 0)
			return ret;

		size += len;
	}
	return size;
}
Exemple #10
0
static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
{
	int rc, status;
	ssize_t burstcnt;
	size_t count = 0;
	u8 retries = 0;
	u8 sts = TPM_STS_GO;

	if (len > TPM_BUFSIZE)
		return -E2BIG;	/* command is too long for our tpm, sorry */

	if (request_locality(chip, 0) < 0)
		return -EBUSY;

	status = tpm_tis_i2c_status(chip);
	if ((status & TPM_STS_COMMAND_READY) == 0) {
		tpm_tis_i2c_ready(chip);
		if (wait_for_stat
		    (chip, TPM_STS_COMMAND_READY,
		     chip->vendor.timeout_b, &status) < 0) {
			rc = -ETIME;
			goto out_err;
		}
	}

	while (count < len - 1) {
		burstcnt = get_burstcount(chip);

		/* burstcnt < 0 = TPM is busy */
		if (burstcnt < 0)
			return burstcnt;

		if (burstcnt > (len - 1 - count))
			burstcnt = len - 1 - count;

		rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality),
				   &(buf[count]), burstcnt);
		if (rc == 0)
			count += burstcnt;
		else if (rc < 0)
			retries++;

		/* avoid endless loop in case of broken HW */
		if (retries > MAX_COUNT_LONG) {
			rc = -EIO;
			goto out_err;
		}

		wait_for_stat(chip, TPM_STS_VALID,
			      chip->vendor.timeout_c, &status);

		if ((status & TPM_STS_DATA_EXPECT) == 0) {
			rc = -EIO;
			goto out_err;
		}

	}

	/* write last byte */
	iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1);
	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
	if ((status & TPM_STS_DATA_EXPECT) != 0) {
		rc = -EIO;
		goto out_err;
	}

	/* go and do it */
	iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1);

	return len;
out_err:
	tpm_tis_i2c_ready(chip);
	/* The TPM needs some time to clean up here,
	 * so we sleep rather than keeping the bus busy
	 */
	usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI);
	release_locality(chip, chip->vendor.locality, 0);
	return rc;
}
Exemple #11
0
/*
 * 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 status,
	    burstcnt = 0, i, size;
	int ret;
	u8 data;
	struct i2c_client *client;

	if (chip == NULL)
		return -EBUSY;
	if (len < TPM_HEADER_SIZE)
		return -EBUSY;

	client = (struct i2c_client *)TPM_VPRIV(chip);

	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;
}
Exemple #12
0
/*
 * st33zp24_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 st33zp24_send(struct tpm_chip *chip, unsigned char *buf,
			 size_t len)
{
	struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
	u32 status, i, size, ordinal;
	int burstcnt = 0;
	int ret;
	u8 data;

	if (!chip)
		return -EBUSY;
	if (len < TPM_HEADER_SIZE)
		return -EBUSY;

	ret = request_locality(chip);
	if (ret < 0)
		return ret;

	status = st33zp24_status(chip);
	if ((status & TPM_STS_COMMAND_READY) == 0) {
		st33zp24_cancel(chip);
		if (wait_for_stat
		    (chip, TPM_STS_COMMAND_READY, chip->timeout_b,
		     &tpm_dev->read_queue, false) < 0) {
			ret = -ETIME;
			goto out_err;
		}
	}

	for (i = 0; i < len - 1;) {
		burstcnt = get_burstcount(chip);
		if (burstcnt < 0)
			return burstcnt;
		size = min_t(int, len - i - 1, burstcnt);
		ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_DATA_FIFO,
					 buf + i, size);
		if (ret < 0)
			goto out_err;

		i += size;
	}

	status = st33zp24_status(chip);
	if ((status & TPM_STS_DATA_EXPECT) == 0) {
		ret = -EIO;
		goto out_err;
	}

	ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_DATA_FIFO,
				 buf + len - 1, 1);
	if (ret < 0)
		goto out_err;

	status = st33zp24_status(chip);
	if ((status & TPM_STS_DATA_EXPECT) != 0) {
		ret = -EIO;
		goto out_err;
	}

	data = TPM_STS_GO;
	ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_STS, &data, 1);
	if (ret < 0)
		goto out_err;

	if (chip->flags & TPM_CHIP_FLAG_IRQ) {
		ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));

		ret = wait_for_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
				tpm_calc_ordinal_duration(chip, ordinal),
				&tpm_dev->read_queue, false);
		if (ret < 0)
			goto out_err;
	}

	return len;
out_err:
	st33zp24_cancel(chip);
	release_locality(chip);
	return ret;
}
Exemple #13
0
int tpm_tis_send(struct tpm_chip* tpm, uint8_t* buf, size_t len) {
   int rc;
   int status, burstcnt = 0;
   int count = 0;
   uint32_t ordinal;

   if(tpm_tis_request_locality(tpm, tpm->locality) < 0) {
      return -EBUSY;
   }

   status = tpm_tis_status(tpm);
   if((status & TPM_STS_COMMAND_READY) == 0) {
      tpm_tis_ready(tpm);
      if(wait_for_stat(tpm, TPM_STS_COMMAND_READY, tpm->timeout_b, &tpm->int_queue) < 0) {
	 rc = -ETIME;
	 goto out_err;
      }
   }

   while(count < len - 1) {
      burstcnt = get_burstcount(tpm);
      for(;burstcnt > 0 && count < len -1; --burstcnt) {
	 iowrite8(TPM_DATA_FIFO(tpm, tpm->locality), buf[count++]);
      }

      wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c, &tpm->int_queue);
      status = tpm_tis_status(tpm);
      if((status & TPM_STS_DATA_EXPECT) == 0) {
	 rc = -EIO;
	 goto out_err;
      }
   }

   /*Write last byte*/
   iowrite8(TPM_DATA_FIFO(tpm, tpm->locality), buf[count]);
   wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c, &tpm->read_queue);
   status = tpm_tis_status(tpm);
   if((status & TPM_STS_DATA_EXPECT) != 0) {
      rc = -EIO;
      goto out_err;
   }

   /*go and do it*/
   iowrite8(TPM_STS(tpm, tpm->locality), TPM_STS_GO);

   if(tpm->irq) {
      /*Wait for interrupt */
      ordinal = be32_to_cpu(*(buf + 6));
      if(wait_for_stat(tpm,
	       TPM_STS_DATA_AVAIL | TPM_STS_VALID,
	       tpm_calc_ordinal_duration(tpm, ordinal),
	       &tpm->read_queue) < 0) {
	 rc = -ETIME;
	 goto out_err;
      }
   }
#ifdef HAVE_LIBC
   if(tpm->fd >= 0) {
      files[tpm->fd].read = 0;
      files[tpm->fd].tpm_tis.respgot = 0;
      files[tpm->fd].tpm_tis.offset = 0;
   }
#endif
   return len;

out_err:
   tpm_tis_ready(tpm);
   release_locality(tpm, tpm->locality, 0);
   return rc;
}