Example #1
0
static int tpmfront_remove(struct xenbus_device *dev)
{
	struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
	struct tpm_private *priv = TPM_VPRIV(chip);
	tpm_chip_unregister(chip);
	ring_free(priv);
	TPM_VPRIV(chip) = NULL;
	return 0;
}
Example #2
0
static int vtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{
	struct tpm_private *priv = TPM_VPRIV(chip);
	struct vtpm_shared_page *shr = priv->shr;
	unsigned int offset = shr_data_offset(shr);
	size_t length = shr->length;

	if (shr->state == VTPM_STATE_IDLE)
		return -ECANCELED;

	/* In theory the wait at the end of _send makes this one unnecessary */
	if (wait_for_tpm_stat(chip, VTPM_STATUS_RESULT, chip->vendor.timeout_c,
			&chip->vendor.read_queue, true) < 0) {
		vtpm_cancel(chip);
		return -ETIME;
	}

	if (offset > PAGE_SIZE)
		return -EIO;

	if (offset + length > PAGE_SIZE)
		length = PAGE_SIZE - offset;

	if (length > count)
		length = count;

	memcpy(buf, offset + (u8 *)shr, length);

	return length;
}
/**
 * ibmvtpm_get_data - Retrieve ibm vtpm data
 * @dev:	device struct
 *
 * Return value:
 *	vtpm device struct
 */
static struct ibmvtpm_dev *ibmvtpm_get_data(const struct device *dev)
{
	struct tpm_chip *chip = dev_get_drvdata(dev);
	if (chip)
		return (struct ibmvtpm_dev *)TPM_VPRIV(chip);
	return NULL;
}
/**
 * tpm_ibmvtpm_recv - Receive data after send
 * @chip:	tpm chip struct
 * @buf:	buffer to read
 * count:	size of buffer
 *
 * Return value:
 *	Number of bytes read
 */
static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{
	struct ibmvtpm_dev *ibmvtpm;
	u16 len;
	int sig;

	ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);

	if (!ibmvtpm->rtce_buf) {
		dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
		return 0;
	}

	sig = wait_event_interruptible(ibmvtpm->wq, ibmvtpm->res_len != 0);
	if (sig)
		return -EINTR;

	len = ibmvtpm->res_len;

	if (count < len) {
		dev_err(ibmvtpm->dev,
			"Invalid size in recv: count=%ld, crq_size=%d\n",
			count, len);
		return -EIO;
	}

	spin_lock(&ibmvtpm->rtce_lock);
	memcpy((void *)buf, (void *)ibmvtpm->rtce_buf, len);
	memset(ibmvtpm->rtce_buf, 0, len);
	ibmvtpm->res_len = 0;
	spin_unlock(&ibmvtpm->rtce_lock);
	return len;
}
/*
 * 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;
}
Example #6
0
static void vtpm_cancel(struct tpm_chip *chip)
{
	struct tpm_private *priv = TPM_VPRIV(chip);
	priv->shr->state = VTPM_STATE_CANCEL;
	wmb();
	notify_remote_via_evtchn(priv->evtchn);
}
Example #7
0
/*
 * 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.
 * @param: check_cancel, does the command can be cancelled ?
 * @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, bool check_cancel)
{
	unsigned long stop;
	int ret;
	bool canceled = false;
	bool condition;
	u32 cur_intrs;
	u8 interrupt, status;
	struct tpm_stm_dev *tpm_dev;

	tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);

	/* check current status */
	status = tpm_stm_i2c_status(chip);
	if ((status & mask) == mask)
		return 0;

	stop = jiffies + timeout;

	if (chip->vendor.irq) {
		cur_intrs = tpm_dev->intrs;
		interrupt = clear_interruption(tpm_dev);
		enable_irq(chip->vendor.irq);

again:
		timeout = stop - jiffies;
		if ((long) timeout <= 0)
			return -1;

		ret = wait_event_interruptible_timeout(*queue,
					cur_intrs != tpm_dev->intrs, timeout);

		interrupt |= clear_interruption(tpm_dev);
		status = interrupt_to_status(interrupt);
		condition = wait_for_tpm_stat_cond(chip, mask,
						   check_cancel, &canceled);

		if (ret >= 0 && condition) {
			if (canceled)
				return -ECANCELED;
			return 0;
		}
		if (ret == -ERESTARTSYS && freezing(current)) {
			clear_thread_flag(TIF_SIGPENDING);
			goto again;
		}
		disable_irq_nosync(chip->vendor.irq);

	} else {
		do {
			msleep(TPM_TIMEOUT);
			status = chip->ops->status(chip);
			if ((status & mask) == mask)
				return 0;
		} while (time_before(jiffies, stop));
	}

	return -ETIME;
} /* wait_for_stat() */
Example #8
0
static int tpm_stm_i2c_request_resources(struct i2c_client *client,
					 struct tpm_chip *chip)
{
	struct st33zp24_platform_data *pdata;
	struct tpm_stm_dev *tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);
	int ret;

	pdata = client->dev.platform_data;
	if (!pdata) {
		dev_err(chip->pdev, "No platform data\n");
		return -ENODEV;
	}

	/* store for late use */
	tpm_dev->io_lpcpd = pdata->io_lpcpd;

	if (gpio_is_valid(pdata->io_lpcpd)) {
		ret = devm_gpio_request_one(&client->dev,
				pdata->io_lpcpd, GPIOF_OUT_INIT_HIGH,
				"TPM IO_LPCPD");
		if (ret) {
			dev_err(chip->pdev, "%s : reset gpio_request failed\n",
				__FILE__);
			return ret;
		}
	}

	return 0;
}
Example #9
0
/*
 * 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 *) TPM_VPRIV(chip);

	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() */
Example #10
0
/*
 * 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 ret;
	struct tpm_stm_dev *tpm_dev;
	u8 data;

	if (check_locality(chip) == chip->vendor.locality)
		return chip->vendor.locality;

	tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);

	data = TPM_ACCESS_REQUEST_USE;
	ret = I2C_WRITE_DATA(tpm_dev, TPM_ACCESS, &data, 1);
	if (ret < 0)
		goto end;

	stop = jiffies + chip->vendor.timeout_a;

	/* Request locality is usually effective after the request */
	do {
		if (check_locality(chip) >= 0)
			return chip->vendor.locality;
		msleep(TPM_TIMEOUT);
	} while (time_before(jiffies, stop));
	ret = -EACCES;
end:
	return ret;
} /* request_locality() */
Example #11
0
/*
 * 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 *) TPM_VPRIV(chip);

	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() */
Example #12
0
/*
 * 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 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 *) TPM_VPRIV(chip))->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);

		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;
}
Example #13
0
/*
 * 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 *) TPM_VPRIV(chip);

	I2C_READ_DATA(client, TPM_STS, &data, 1);
	return data;
}				/* tpm_stm_i2c_status() */
Example #14
0
/*
 * release_locality release the active locality
 * @param: chip, the tpm chip description.
 */
static void release_locality(struct tpm_chip *chip)
{
	struct tpm_stm_dev *tpm_dev;
	u8 data;

	tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);
	data = TPM_ACCESS_ACTIVE_LOCALITY;

	I2C_WRITE_DATA(tpm_dev, TPM_ACCESS, &data, 1);
}
Example #15
0
/*
 * 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 tpm_stm_dev *tpm_dev;
	u8 data;

	tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);

	I2C_READ_DATA(tpm_dev, TPM_STS, &data, 1);
	return data;
} /* tpm_stm_i2c_status() */
Example #16
0
/*
 * 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 tpm_stm_dev *tpm_dev;
	u8 data;

	tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);

	data = TPM_STS_COMMAND_READY;
	I2C_WRITE_DATA(tpm_dev, TPM_STS, &data, 1);
} /* tpm_stm_i2c_cancel() */
Example #17
0
/*
 * 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 *) TPM_VPRIV(chip);
	data = TPM_ACCESS_ACTIVE_LOCALITY;

	I2C_WRITE_DATA(client, TPM_ACCESS, &data, 1);
}
Example #18
0
/*
 * 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 *) TPM_VPRIV(chip);

	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() */
Example #19
0
/*
 * 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 tpm_stm_dev *tpm_dev;

	tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);

	tpm_dev->intrs++;
	wake_up_interruptible(&chip->vendor.read_queue);
	disable_irq_nosync(chip->vendor.irq);

	return IRQ_HANDLED;
} /* tpm_ioserirq_handler() */
Example #20
0
/*
 * 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 *) TPM_VPRIV(chip);
	pin_infos = client->dev.platform_data;

	complete(&pin_infos->irq_detection);
	return IRQ_HANDLED;
} /* tpm_ioserirq_handler() */
Example #21
0
static int setup_chip(struct device *dev, struct tpm_private *priv)
{
	struct tpm_chip *chip;

	chip = tpmm_chip_alloc(dev, &tpm_vtpm);
	if (IS_ERR(chip))
		return PTR_ERR(chip);

	init_waitqueue_head(&chip->vendor.read_queue);

	priv->chip = chip;
	TPM_VPRIV(chip) = priv;

	return 0;
}
Example #22
0
static u8 vtpm_status(struct tpm_chip *chip)
{
	struct tpm_private *priv = TPM_VPRIV(chip);
	switch (priv->shr->state) {
	case VTPM_STATE_IDLE:
		return VTPM_STATUS_IDLE | VTPM_STATUS_CANCELED;
	case VTPM_STATE_FINISH:
		return VTPM_STATUS_IDLE | VTPM_STATUS_RESULT;
	case VTPM_STATE_SUBMIT:
	case VTPM_STATE_CANCEL: /* cancel requested, not yet canceled */
		return VTPM_STATUS_RUNNING;
	default:
		return 0;
	}
}
static int setup_chip(struct device *dev, struct tpm_private *priv)
{
	struct tpm_chip *chip;

	chip = tpm_register_hardware(dev, &tpm_vtpm);
	if (!chip)
		return -ENODEV;

	init_waitqueue_head(&chip->vendor.read_queue);

	priv->chip = chip;
	TPM_VPRIV(chip) = priv;

	return 0;
}
Example #24
0
/*
 * 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 tpm_stm_dev *tpm_dev;
	u8 data;
	u8 status;

	tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);

	status = I2C_READ_DATA(tpm_dev, 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() */
Example #25
0
/*
 * 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 *) TPM_VPRIV(chip);

	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() */
Example #26
0
static int wait_for_serirq_timeout(struct tpm_chip *chip, bool condition,
				 unsigned long timeout)
{
	int status = 2;
	struct i2c_client *client;

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

	status = _wait_for_interrupt_serirq_timeout(chip, timeout);
	if (!status) {
		status = -EBUSY;
	} else{
		clear_interruption(client);
		if (condition)
			status = 1;
	}
	return status;
}
Example #27
0
/*
 * _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 *) TPM_VPRIV(chip);
	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() */
Example #28
0
static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
{
	struct tpm_private *priv = TPM_VPRIV(chip);
	struct vtpm_shared_page *shr = priv->shr;
	unsigned int offset = shr_data_offset(shr);

	u32 ordinal;
	unsigned long duration;

	if (offset > PAGE_SIZE)
		return -EINVAL;

	if (offset + count > PAGE_SIZE)
		return -EINVAL;

	/* Wait for completion of any existing command or cancellation */
	if (wait_for_tpm_stat(chip, VTPM_STATUS_IDLE, chip->vendor.timeout_c,
			&chip->vendor.read_queue, true) < 0) {
		vtpm_cancel(chip);
		return -ETIME;
	}

	memcpy(offset + (u8 *)shr, buf, count);
	shr->length = count;
	barrier();
	shr->state = VTPM_STATE_SUBMIT;
	wmb();
	notify_remote_via_evtchn(priv->evtchn);

	ordinal = be32_to_cpu(((struct tpm_input_header*)buf)->ordinal);
	duration = tpm_calc_ordinal_duration(chip, ordinal);

	if (wait_for_tpm_stat(chip, VTPM_STATUS_IDLE, duration,
			&chip->vendor.read_queue, true) < 0) {
		/* got a signal or timeout, try to cancel */
		vtpm_cancel(chip);
		return -ETIME;
	}

	return count;
}
/**
 * tpm_ibmvtpm_send - Send tpm request
 * @chip:	tpm chip struct
 * @buf:	buffer contains data to send
 * count:	size of buffer
 *
 * Return value:
 *	Number of bytes sent
 */
static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
{
	struct ibmvtpm_dev *ibmvtpm;
	struct ibmvtpm_crq crq;
	__be64 *word = (__be64 *)&crq;
	int rc;

	ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);

	if (!ibmvtpm->rtce_buf) {
		dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
		return 0;
	}

	if (count > ibmvtpm->rtce_size) {
		dev_err(ibmvtpm->dev,
			"Invalid size in send: count=%ld, rtce_size=%d\n",
			count, ibmvtpm->rtce_size);
		return -EIO;
	}

	spin_lock(&ibmvtpm->rtce_lock);
	memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count);
	crq.valid = (u8)IBMVTPM_VALID_CMD;
	crq.msg = (u8)VTPM_TPM_COMMAND;
	crq.len = cpu_to_be16(count);
	crq.data = cpu_to_be32(ibmvtpm->rtce_dma_handle);

rc = ibmvtpm_send_crq(ibmvtpm->vdev, be64_to_cpu(word[0]),
		      be64_to_cpu(word[1]));
	if (rc != H_SUCCESS) {
		dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
		rc = 0;
	} else
		rc = count;

	spin_unlock(&ibmvtpm->rtce_lock);
	return rc;
}
Example #30
0
static int tpm_stm_i2c_of_request_resources(struct tpm_chip *chip)
{
	struct device_node *pp;
	struct tpm_stm_dev *tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);
	struct i2c_client *client = tpm_dev->client;
	int gpio;
	int ret;

	pp = client->dev.of_node;
	if (!pp) {
		dev_err(chip->pdev, "No platform data\n");
		return -ENODEV;
	}

	/* Get GPIO from device tree */
	gpio = of_get_named_gpio(pp, "lpcpd-gpios", 0);
	if (gpio < 0) {
		dev_err(chip->pdev, "Failed to retrieve lpcpd-gpios from dts.\n");
		tpm_dev->io_lpcpd = -1;
		/*
		 * lpcpd pin is not specified. This is not an issue as
		 * power management can be also managed by TPM specific
		 * commands. So leave with a success status code.
		 */
		return 0;
	}
	/* GPIO request and configuration */
	ret = devm_gpio_request_one(&client->dev, gpio,
			GPIOF_OUT_INIT_HIGH, "TPM IO LPCPD");
	if (ret) {
		dev_err(chip->pdev, "Failed to request lpcpd pin\n");
		return -ENODEV;
	}
	tpm_dev->io_lpcpd = gpio;

	return 0;
}