Commit 7a1e8b80 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security

Pull security subsystem updates from James Morris:
 "Highlights:

   - TPM core and driver updates/fixes
   - IPv6 security labeling (CALIPSO)
   - Lots of Apparmor fixes
   - Seccomp: remove 2-phase API, close hole where ptrace can change
     syscall #"

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (156 commits)
  apparmor: fix SECURITY_APPARMOR_HASH_DEFAULT parameter handling
  tpm: Add TPM 2.0 support to the Nuvoton i2c driver (NPCT6xx family)
  tpm: Factor out common startup code
  tpm: use devm_add_action_or_reset
  tpm2_i2c_nuvoton: add irq validity check
  tpm: read burstcount from TPM_STS in one 32-bit transaction
  tpm: fix byte-order for the value read by tpm2_get_tpm_pt
  tpm_tis_core: convert max timeouts from msec to jiffies
  apparmor: fix arg_size computation for when setprocattr is null terminated
  apparmor: fix oops, validate buffer size in apparmor_setprocattr()
  apparmor: do not expose kernel stack
  apparmor: fix module parameters can be changed after policy is locked
  apparmor: fix oops in profile_unpack() when policy_db is not present
  apparmor: don't check for vmalloc_addr if kvzalloc() failed
  apparmor: add missing id bounds check on dfa verification
  apparmor: allow SYS_CAP_RESOURCE to be sufficient to prlimit another task
  apparmor: use list_next_entry instead of list_entry_next
  apparmor: fix refcount race when finding a child profile
  apparmor: fix ref count leak when profile sha1 hash is read
  apparmor: check that xindex is in trans_table bounds
  ...
parents a867d734 7616ac70
/* /*
* STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24 * STMicroelectronics TPM I2C Linux driver for TPM ST33ZP24
* Copyright (C) 2009 - 2015 STMicroelectronics * Copyright (C) 2009 - 2016 STMicroelectronics
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -19,11 +19,14 @@ ...@@ -19,11 +19,14 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/acpi.h>
#include <linux/tpm.h> #include <linux/tpm.h>
#include <linux/platform_data/st33zp24.h> #include <linux/platform_data/st33zp24.h>
#include "../tpm.h"
#include "st33zp24.h" #include "st33zp24.h"
#define TPM_DUMMY_BYTE 0xAA #define TPM_DUMMY_BYTE 0xAA
...@@ -108,11 +111,40 @@ static const struct st33zp24_phy_ops i2c_phy_ops = { ...@@ -108,11 +111,40 @@ static const struct st33zp24_phy_ops i2c_phy_ops = {
.recv = st33zp24_i2c_recv, .recv = st33zp24_i2c_recv,
}; };
#ifdef CONFIG_OF static int st33zp24_i2c_acpi_request_resources(struct i2c_client *client)
static int st33zp24_i2c_of_request_resources(struct st33zp24_i2c_phy *phy)
{ {
struct tpm_chip *chip = i2c_get_clientdata(client);
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
struct st33zp24_i2c_phy *phy = tpm_dev->phy_id;
struct gpio_desc *gpiod_lpcpd;
struct device *dev = &client->dev;
/* Get LPCPD GPIO from ACPI */
gpiod_lpcpd = devm_gpiod_get_index(dev, "TPM IO LPCPD", 1,
GPIOD_OUT_HIGH);
if (IS_ERR(gpiod_lpcpd)) {
dev_err(&client->dev,
"Failed to retrieve lpcpd-gpios from acpi.\n");
phy->io_lpcpd = -1;
/*
* lpcpd pin is not specified. This is not an issue as
* power management can be also managed by TPM specific
* commands. So leave with a success status code.
*/
return 0;
}
phy->io_lpcpd = desc_to_gpio(gpiod_lpcpd);
return 0;
}
static int st33zp24_i2c_of_request_resources(struct i2c_client *client)
{
struct tpm_chip *chip = i2c_get_clientdata(client);
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
struct st33zp24_i2c_phy *phy = tpm_dev->phy_id;
struct device_node *pp; struct device_node *pp;
struct i2c_client *client = phy->client;
int gpio; int gpio;
int ret; int ret;
...@@ -146,16 +178,12 @@ static int st33zp24_i2c_of_request_resources(struct st33zp24_i2c_phy *phy) ...@@ -146,16 +178,12 @@ static int st33zp24_i2c_of_request_resources(struct st33zp24_i2c_phy *phy)
return 0; return 0;
} }
#else
static int st33zp24_i2c_of_request_resources(struct st33zp24_i2c_phy *phy)
{
return -ENODEV;
}
#endif
static int st33zp24_i2c_request_resources(struct i2c_client *client, static int st33zp24_i2c_request_resources(struct i2c_client *client)
struct st33zp24_i2c_phy *phy)
{ {
struct tpm_chip *chip = i2c_get_clientdata(client);
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
struct st33zp24_i2c_phy *phy = tpm_dev->phy_id;
struct st33zp24_platform_data *pdata; struct st33zp24_platform_data *pdata;
int ret; int ret;
...@@ -212,13 +240,18 @@ static int st33zp24_i2c_probe(struct i2c_client *client, ...@@ -212,13 +240,18 @@ static int st33zp24_i2c_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
phy->client = client; phy->client = client;
pdata = client->dev.platform_data; pdata = client->dev.platform_data;
if (!pdata && client->dev.of_node) { if (!pdata && client->dev.of_node) {
ret = st33zp24_i2c_of_request_resources(phy); ret = st33zp24_i2c_of_request_resources(client);
if (ret) if (ret)
return ret; return ret;
} else if (pdata) { } else if (pdata) {
ret = st33zp24_i2c_request_resources(client, phy); ret = st33zp24_i2c_request_resources(client);
if (ret)
return ret;
} else if (ACPI_HANDLE(&client->dev)) {
ret = st33zp24_i2c_acpi_request_resources(client);
if (ret) if (ret)
return ret; return ret;
} }
...@@ -245,13 +278,17 @@ static const struct i2c_device_id st33zp24_i2c_id[] = { ...@@ -245,13 +278,17 @@ static const struct i2c_device_id st33zp24_i2c_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, st33zp24_i2c_id); MODULE_DEVICE_TABLE(i2c, st33zp24_i2c_id);
#ifdef CONFIG_OF
static const struct of_device_id of_st33zp24_i2c_match[] = { static const struct of_device_id of_st33zp24_i2c_match[] = {
{ .compatible = "st,st33zp24-i2c", }, { .compatible = "st,st33zp24-i2c", },
{} {}
}; };
MODULE_DEVICE_TABLE(of, of_st33zp24_i2c_match); MODULE_DEVICE_TABLE(of, of_st33zp24_i2c_match);
#endif
static const struct acpi_device_id st33zp24_i2c_acpi_match[] = {
{"SMO3324"},
{}
};
MODULE_DEVICE_TABLE(acpi, st33zp24_i2c_acpi_match);
static SIMPLE_DEV_PM_OPS(st33zp24_i2c_ops, st33zp24_pm_suspend, static SIMPLE_DEV_PM_OPS(st33zp24_i2c_ops, st33zp24_pm_suspend,
st33zp24_pm_resume); st33zp24_pm_resume);
...@@ -261,6 +298,7 @@ static struct i2c_driver st33zp24_i2c_driver = { ...@@ -261,6 +298,7 @@ static struct i2c_driver st33zp24_i2c_driver = {
.name = TPM_ST33_I2C, .name = TPM_ST33_I2C,
.pm = &st33zp24_i2c_ops, .pm = &st33zp24_i2c_ops,
.of_match_table = of_match_ptr(of_st33zp24_i2c_match), .of_match_table = of_match_ptr(of_st33zp24_i2c_match),
.acpi_match_table = ACPI_PTR(st33zp24_i2c_acpi_match),
}, },
.probe = st33zp24_i2c_probe, .probe = st33zp24_i2c_probe,
.remove = st33zp24_i2c_remove, .remove = st33zp24_i2c_remove,
......
/* /*
* STMicroelectronics TPM SPI Linux driver for TPM ST33ZP24 * STMicroelectronics TPM SPI Linux driver for TPM ST33ZP24
* Copyright (C) 2009 - 2015 STMicroelectronics * Copyright (C) 2009 - 2016 STMicroelectronics
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -19,11 +19,14 @@ ...@@ -19,11 +19,14 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/acpi.h>
#include <linux/tpm.h> #include <linux/tpm.h>
#include <linux/platform_data/st33zp24.h> #include <linux/platform_data/st33zp24.h>
#include "../tpm.h"
#include "st33zp24.h" #include "st33zp24.h"
#define TPM_DATA_FIFO 0x24 #define TPM_DATA_FIFO 0x24
...@@ -66,7 +69,7 @@ ...@@ -66,7 +69,7 @@
struct st33zp24_spi_phy { struct st33zp24_spi_phy {
struct spi_device *spi_device; struct spi_device *spi_device;
struct spi_transfer spi_xfer;
u8 tx_buf[ST33ZP24_SPI_BUFFER_SIZE]; u8 tx_buf[ST33ZP24_SPI_BUFFER_SIZE];
u8 rx_buf[ST33ZP24_SPI_BUFFER_SIZE]; u8 rx_buf[ST33ZP24_SPI_BUFFER_SIZE];
...@@ -110,43 +113,39 @@ static int st33zp24_status_to_errno(u8 code) ...@@ -110,43 +113,39 @@ static int st33zp24_status_to_errno(u8 code)
static int st33zp24_spi_send(void *phy_id, u8 tpm_register, u8 *tpm_data, static int st33zp24_spi_send(void *phy_id, u8 tpm_register, u8 *tpm_data,
int tpm_size) int tpm_size)
{ {
u8 data = 0; int total_length = 0, ret = 0;
int total_length = 0, nbr_dummy_bytes = 0, ret = 0;
struct st33zp24_spi_phy *phy = phy_id; struct st33zp24_spi_phy *phy = phy_id;
struct spi_device *dev = phy->spi_device; struct spi_device *dev = phy->spi_device;
u8 *tx_buf = (u8 *)phy->spi_xfer.tx_buf; struct spi_transfer spi_xfer = {
u8 *rx_buf = phy->spi_xfer.rx_buf; .tx_buf = phy->tx_buf,
.rx_buf = phy->rx_buf,
};
/* Pre-Header */ /* Pre-Header */
data = TPM_WRITE_DIRECTION | LOCALITY0; phy->tx_buf[total_length++] = TPM_WRITE_DIRECTION | LOCALITY0;
memcpy(tx_buf + total_length, &data, sizeof(data)); phy->tx_buf[total_length++] = tpm_register;
total_length++;
data = tpm_register;
memcpy(tx_buf + total_length, &data, sizeof(data));
total_length++;
if (tpm_size > 0 && tpm_register == TPM_DATA_FIFO) { if (tpm_size > 0 && tpm_register == TPM_DATA_FIFO) {
tx_buf[total_length++] = tpm_size >> 8; phy->tx_buf[total_length++] = tpm_size >> 8;
tx_buf[total_length++] = tpm_size; phy->tx_buf[total_length++] = tpm_size;
} }
memcpy(&tx_buf[total_length], tpm_data, tpm_size); memcpy(&phy->tx_buf[total_length], tpm_data, tpm_size);
total_length += tpm_size; total_length += tpm_size;
nbr_dummy_bytes = phy->latency; memset(&phy->tx_buf[total_length], TPM_DUMMY_BYTE, phy->latency);
memset(&tx_buf[total_length], TPM_DUMMY_BYTE, nbr_dummy_bytes);
phy->spi_xfer.len = total_length + nbr_dummy_bytes; spi_xfer.len = total_length + phy->latency;
ret = spi_sync_transfer(dev, &phy->spi_xfer, 1); ret = spi_sync_transfer(dev, &spi_xfer, 1);
if (ret == 0) if (ret == 0)
ret = rx_buf[total_length + nbr_dummy_bytes - 1]; ret = phy->rx_buf[total_length + phy->latency - 1];
return st33zp24_status_to_errno(ret); return st33zp24_status_to_errno(ret);
} /* st33zp24_spi_send() */ } /* st33zp24_spi_send() */
/* /*
* read8_recv * st33zp24_spi_read8_recv
* Recv byte from the TIS register according to the ST33ZP24 SPI protocol. * Recv byte from the TIS register according to the ST33ZP24 SPI protocol.
* @param: phy_id, the phy description * @param: phy_id, the phy description
* @param: tpm_register, the tpm tis register where the data should be read * @param: tpm_register, the tpm tis register where the data should be read
...@@ -154,40 +153,37 @@ static int st33zp24_spi_send(void *phy_id, u8 tpm_register, u8 *tpm_data, ...@@ -154,40 +153,37 @@ static int st33zp24_spi_send(void *phy_id, u8 tpm_register, u8 *tpm_data,
* @param: tpm_size, tpm TPM response size to read. * @param: tpm_size, tpm TPM response size to read.
* @return: should be zero if success else a negative error code. * @return: should be zero if success else a negative error code.
*/ */
static int read8_reg(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size) static int st33zp24_spi_read8_reg(void *phy_id, u8 tpm_register, u8 *tpm_data,
int tpm_size)
{ {
u8 data = 0; int total_length = 0, ret;
int total_length = 0, nbr_dummy_bytes, ret;
struct st33zp24_spi_phy *phy = phy_id; struct st33zp24_spi_phy *phy = phy_id;
struct spi_device *dev = phy->spi_device; struct spi_device *dev = phy->spi_device;
u8 *tx_buf = (u8 *)phy->spi_xfer.tx_buf; struct spi_transfer spi_xfer = {
u8 *rx_buf = phy->spi_xfer.rx_buf; .tx_buf = phy->tx_buf,
.rx_buf = phy->rx_buf,
};
/* Pre-Header */ /* Pre-Header */
data = LOCALITY0; phy->tx_buf[total_length++] = LOCALITY0;
memcpy(tx_buf + total_length, &data, sizeof(data)); phy->tx_buf[total_length++] = tpm_register;
total_length++;
data = tpm_register;
memcpy(tx_buf + total_length, &data, sizeof(data));
total_length++;
nbr_dummy_bytes = phy->latency; memset(&phy->tx_buf[total_length], TPM_DUMMY_BYTE,
memset(&tx_buf[total_length], TPM_DUMMY_BYTE, phy->latency + tpm_size);
nbr_dummy_bytes + tpm_size);
phy->spi_xfer.len = total_length + nbr_dummy_bytes + tpm_size; spi_xfer.len = total_length + phy->latency + tpm_size;
/* header + status byte + size of the data + status byte */ /* header + status byte + size of the data + status byte */
ret = spi_sync_transfer(dev, &phy->spi_xfer, 1); ret = spi_sync_transfer(dev, &spi_xfer, 1);
if (tpm_size > 0 && ret == 0) { if (tpm_size > 0 && ret == 0) {
ret = rx_buf[total_length + nbr_dummy_bytes - 1]; ret = phy->rx_buf[total_length + phy->latency - 1];
memcpy(tpm_data, rx_buf + total_length + nbr_dummy_bytes, memcpy(tpm_data, phy->rx_buf + total_length + phy->latency,
tpm_size); tpm_size);
} }
return ret; return ret;
} /* read8_reg() */ } /* st33zp24_spi_read8_reg() */
/* /*
* st33zp24_spi_recv * st33zp24_spi_recv
...@@ -203,13 +199,13 @@ static int st33zp24_spi_recv(void *phy_id, u8 tpm_register, u8 *tpm_data, ...@@ -203,13 +199,13 @@ static int st33zp24_spi_recv(void *phy_id, u8 tpm_register, u8 *tpm_data,
{ {
int ret; int ret;
ret = read8_reg(phy_id, tpm_register, tpm_data, tpm_size); ret = st33zp24_spi_read8_reg(phy_id, tpm_register, tpm_data, tpm_size);
if (!st33zp24_status_to_errno(ret)) if (!st33zp24_status_to_errno(ret))
return tpm_size; return tpm_size;
return ret; return ret;
} /* st33zp24_spi_recv() */ } /* st33zp24_spi_recv() */
static int evaluate_latency(void *phy_id) static int st33zp24_spi_evaluate_latency(void *phy_id)
{ {
struct st33zp24_spi_phy *phy = phy_id; struct st33zp24_spi_phy *phy = phy_id;
int latency = 1, status = 0; int latency = 1, status = 0;
...@@ -217,9 +213,15 @@ static int evaluate_latency(void *phy_id) ...@@ -217,9 +213,15 @@ static int evaluate_latency(void *phy_id)
while (!status && latency < MAX_SPI_LATENCY) { while (!status && latency < MAX_SPI_LATENCY) {
phy->latency = latency; phy->latency = latency;
status = read8_reg(phy_id, TPM_INTF_CAPABILITY, &data, 1); status = st33zp24_spi_read8_reg(phy_id, TPM_INTF_CAPABILITY,
&data, 1);
latency++; latency++;
} }
if (status < 0)
return status;
if (latency == MAX_SPI_LATENCY)
return -ENODEV;
return latency - 1; return latency - 1;
} /* evaluate_latency() */ } /* evaluate_latency() */
...@@ -228,24 +230,52 @@ static const struct st33zp24_phy_ops spi_phy_ops = { ...@@ -228,24 +230,52 @@ static const struct st33zp24_phy_ops spi_phy_ops = {
.recv = st33zp24_spi_recv, .recv = st33zp24_spi_recv,
}; };
#ifdef CONFIG_OF static int st33zp24_spi_acpi_request_resources(struct spi_device *spi_dev)
static int tpm_stm_spi_of_request_resources(struct st33zp24_spi_phy *phy)
{ {
struct tpm_chip *chip = spi_get_drvdata(spi_dev);
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
struct st33zp24_spi_phy *phy = tpm_dev->phy_id;
struct gpio_desc *gpiod_lpcpd;
struct device *dev = &spi_dev->dev;
/* Get LPCPD GPIO from ACPI */
gpiod_lpcpd = devm_gpiod_get_index(dev, "TPM IO LPCPD", 1,
GPIOD_OUT_HIGH);
if (IS_ERR(gpiod_lpcpd)) {
dev_err(dev, "Failed to retrieve lpcpd-gpios from acpi.\n");
phy->io_lpcpd = -1;
/*
* lpcpd pin is not specified. This is not an issue as
* power management can be also managed by TPM specific
* commands. So leave with a success status code.
*/
return 0;
}
phy->io_lpcpd = desc_to_gpio(gpiod_lpcpd);
return 0;
}
static int st33zp24_spi_of_request_resources(struct spi_device *spi_dev)
{
struct tpm_chip *chip = spi_get_drvdata(spi_dev);
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
struct st33zp24_spi_phy *phy = tpm_dev->phy_id;
struct device_node *pp; struct device_node *pp;
struct spi_device *dev = phy->spi_device;
int gpio; int gpio;
int ret; int ret;
pp = dev->dev.of_node; pp = spi_dev->dev.of_node;
if (!pp) { if (!pp) {
dev_err(&dev->dev, "No platform data\n"); dev_err(&spi_dev->dev, "No platform data\n");
return -ENODEV; return -ENODEV;
} }
/* Get GPIO from device tree */ /* Get GPIO from device tree */
gpio = of_get_named_gpio(pp, "lpcpd-gpios", 0); gpio = of_get_named_gpio(pp, "lpcpd-gpios", 0);
if (gpio < 0) { if (gpio < 0) {
dev_err(&dev->dev, dev_err(&spi_dev->dev,
"Failed to retrieve lpcpd-gpios from dts.\n"); "Failed to retrieve lpcpd-gpios from dts.\n");
phy->io_lpcpd = -1; phy->io_lpcpd = -1;
/* /*
...@@ -256,26 +286,22 @@ static int tpm_stm_spi_of_request_resources(struct st33zp24_spi_phy *phy) ...@@ -256,26 +286,22 @@ static int tpm_stm_spi_of_request_resources(struct st33zp24_spi_phy *phy)
return 0; return 0;
} }
/* GPIO request and configuration */ /* GPIO request and configuration */
ret = devm_gpio_request_one(&dev->dev, gpio, ret = devm_gpio_request_one(&spi_dev->dev, gpio,
GPIOF_OUT_INIT_HIGH, "TPM IO LPCPD"); GPIOF_OUT_INIT_HIGH, "TPM IO LPCPD");
if (ret) { if (ret) {
dev_err(&dev->dev, "Failed to request lpcpd pin\n"); dev_err(&spi_dev->dev, "Failed to request lpcpd pin\n");
return -ENODEV; return -ENODEV;
} }
phy->io_lpcpd = gpio; phy->io_lpcpd = gpio;
return 0; return 0;
} }
#else
static int tpm_stm_spi_of_request_resources(struct st33zp24_spi_phy *phy)
{
return -ENODEV;
}
#endif
static int tpm_stm_spi_request_resources(struct spi_device *dev, static int st33zp24_spi_request_resources(struct spi_device *dev)
struct st33zp24_spi_phy *phy)
{ {
struct tpm_chip *chip = spi_get_drvdata(dev);
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
struct st33zp24_spi_phy *phy = tpm_dev->phy_id;
struct st33zp24_platform_data *pdata; struct st33zp24_platform_data *pdata;
int ret; int ret;
...@@ -303,13 +329,12 @@ static int tpm_stm_spi_request_resources(struct spi_device *dev, ...@@ -303,13 +329,12 @@ static int tpm_stm_spi_request_resources(struct spi_device *dev,
} }
/* /*
* tpm_st33_spi_probe initialize the TPM device * st33zp24_spi_probe initialize the TPM device
* @param: dev, the spi_device drescription (TPM SPI description). * @param: dev, the spi_device drescription (TPM SPI description).
* @return: 0 in case of success. * @return: 0 in case of success.
* or a negative value describing the error. * or a negative value describing the error.
*/ */
static int static int st33zp24_spi_probe(struct spi_device *dev)
tpm_st33_spi_probe(struct spi_device *dev)
{ {
int ret; int ret;
struct st33zp24_platform_data *pdata; struct st33zp24_platform_data *pdata;
...@@ -328,21 +353,23 @@ tpm_st33_spi_probe(struct spi_device *dev) ...@@ -328,21 +353,23 @@ tpm_st33_spi_probe(struct spi_device *dev)
return -ENOMEM; return -ENOMEM;
phy->spi_device = dev; phy->spi_device = dev;
pdata = dev->dev.platform_data; pdata = dev->dev.platform_data;
if (!pdata && dev->dev.of_node) { if (!pdata && dev->dev.of_node) {
ret = tpm_stm_spi_of_request_resources(phy); ret = st33zp24_spi_of_request_resources(dev);
if (ret) if (ret)
return ret; return ret;
} else if (pdata) { } else if (pdata) {
ret = tpm_stm_spi_request_resources(dev, phy); ret = st33zp24_spi_request_resources(dev);
if (ret)
return ret;
} else if (ACPI_HANDLE(&dev->dev)) {
ret = st33zp24_spi_acpi_request_resources(dev);
if (ret) if (ret)
return ret; return ret;
} }
phy->spi_xfer.tx_buf = phy->tx_buf; phy->latency = st33zp24_spi_evaluate_latency(phy);
phy->spi_xfer.rx_buf = phy->rx_buf;
phy->latency = evaluate_latency(phy);
if (phy->latency <= 0) if (phy->latency <= 0)
return -ENODEV; return -ENODEV;
...@@ -351,11 +378,11 @@ tpm_st33_spi_probe(struct spi_device *dev) ...@@ -351,11 +378,11 @@ tpm_st33_spi_probe(struct spi_device *dev)
} }
/* /*
* tpm_st33_spi_remove remove the TPM device * st33zp24_spi_remove remove the TPM device
* @param: client, the spi_device drescription (TPM SPI description). * @param: client, the spi_device drescription (TPM SPI description).
* @return: 0 in case of success. * @return: 0 in case of success.
*/ */
static int tpm_st33_spi_remove(struct spi_device *dev) static int st33zp24_spi_remove(struct spi_device *dev)
{ {
struct tpm_chip *chip = spi_get_drvdata(dev); struct tpm_chip *chip = spi_get_drvdata(dev);
...@@ -368,29 +395,34 @@ static const struct spi_device_id st33zp24_spi_id[] = { ...@@ -368,29 +395,34 @@ static const struct spi_device_id st33zp24_spi_id[] = {
}; };
MODULE_DEVICE_TABLE(spi, st33zp24_spi_id); MODULE_DEVICE_TABLE(spi, st33zp24_spi_id);
#ifdef CONFIG_OF
static const struct of_device_id of_st33zp24_spi_match[] = { static const struct of_device_id of_st33zp24_spi_match[] = {
{ .compatible = "st,st33zp24-spi", }, { .compatible = "st,st33zp24-spi", },
{} {}
}; };
MODULE_DEVICE_TABLE(of, of_st33zp24_spi_match); MODULE_DEVICE_TABLE(of, of_st33zp24_spi_match);
#endif
static const struct acpi_device_id st33zp24_spi_acpi_match[] = {
{"SMO3324"},
{}
};
MODULE_DEVICE_TABLE(acpi, st33zp24_spi_acpi_match);
static SIMPLE_DEV_PM_OPS(st33zp24_spi_ops, st33zp24_pm_suspend, static SIMPLE_DEV_PM_OPS(st33zp24_spi_ops, st33zp24_pm_suspend,
st33zp24_pm_resume); st33zp24_pm_resume);
static struct spi_driver tpm_st33_spi_driver = { static struct spi_driver st33zp24_spi_driver = {
.driver = { .driver = {
.name = TPM_ST33_SPI, .name = TPM_ST33_SPI,
.pm = &st33zp24_spi_ops, .pm = &st33zp24_spi_ops,
.of_match_table = of_match_ptr(of_st33zp24_spi_match), .of_match_table = of_match_ptr(of_st33zp24_spi_match),
.acpi_match_table = ACPI_PTR(st33zp24_spi_acpi_match),
}, },
.probe = tpm_st33_spi_probe, .probe = st33zp24_spi_probe,
.remove = tpm_st33_spi_remove, .remove = st33zp24_spi_remove,
.id_table = st33zp24_spi_id, .id_table = st33zp24_spi_id,
}; };
module_spi_driver(tpm_st33_spi_driver); module_spi_driver(st33zp24_spi_driver);
MODULE_AUTHOR("TPM support (TPMsupport@list.st.com)"); MODULE_AUTHOR("TPM support (TPMsupport@list.st.com)");
MODULE_DESCRIPTION("STM TPM 1.2 SPI ST33 Driver"); MODULE_DESCRIPTION("STM TPM 1.2 SPI ST33 Driver");
......
/* /*
* STMicroelectronics TPM Linux driver for TPM ST33ZP24 * STMicroelectronics TPM Linux driver for TPM ST33ZP24
* Copyright (C) 2009 - 2015 STMicroelectronics * Copyright (C) 2009 - 2016 STMicroelectronics
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -73,14 +73,6 @@ enum tis_defaults { ...@@ -73,14 +73,6 @@ enum tis_defaults {
TIS_LONG_TIMEOUT = 2000, TIS_LONG_TIMEOUT = 2000,
}; };
struct st33zp24_dev {
struct tpm_chip *chip;
void *phy_id;
const struct st33zp24_phy_ops *ops;
u32 intrs;
int io_lpcpd;
};
/* /*
* clear_interruption clear the pending interrupt. * clear_interruption clear the pending interrupt.
* @param: tpm_dev, the tpm device device. * @param: tpm_dev, the tpm device device.
...@@ -102,11 +94,9 @@ static u8 clear_interruption(struct st33zp24_dev *tpm_dev) ...@@ -102,11 +94,9 @@ static u8 clear_interruption(struct st33zp24_dev *tpm_dev)
*/ */
static void st33zp24_cancel(struct tpm_chip *chip) static void st33zp24_cancel(struct tpm_chip *chip)
{ {
struct st33zp24_dev *tpm_dev; struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
u8 data; u8 data;
tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
data = TPM_STS_COMMAND_READY; data = TPM_STS_COMMAND_READY;
tpm_dev->ops->send(tpm_dev->phy_id, TPM_STS, &data, 1); tpm_dev->ops->send(tpm_dev->phy_id, TPM_STS, &data, 1);
} /* st33zp24_cancel() */ } /* st33zp24_cancel() */
...@@ -118,11 +108,9 @@ static void st33zp24_cancel(struct tpm_chip *chip) ...@@ -118,11 +108,9 @@ static void st33zp24_cancel(struct tpm_chip *chip)
*/ */
static u8 st33zp24_status(struct tpm_chip *chip) static u8 st33zp24_status(struct tpm_chip *chip)
{ {
struct st33zp24_dev *tpm_dev; struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
u8 data; u8 data;
tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS, &data, 1); tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS, &data, 1);
return data; return data;
} /* st33zp24_status() */ } /* st33zp24_status() */
...@@ -134,17 +122,15 @@ static u8 st33zp24_status(struct tpm_chip *chip) ...@@ -134,17 +122,15 @@ static u8 st33zp24_status(struct tpm_chip *chip)
*/ */
static int check_locality(struct tpm_chip *chip) static int check_locality(struct tpm_chip *chip)
{ {
struct st33zp24_dev *tpm_dev; struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
u8 data; u8 data;
u8 status; u8 status;
tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_ACCESS, &data, 1); status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
if (status && (data & if (status && (data &
(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
return chip->vendor.locality; return tpm_dev->locality;
return -EACCES; return -EACCES;
} /* check_locality() */ } /* check_locality() */
...@@ -156,27 +142,25 @@ static int check_locality(struct tpm_chip *chip) ...@@ -156,27 +142,25 @@ static int check_locality(struct tpm_chip *chip)
*/ */
static int request_locality(struct tpm_chip *chip) static int request_locality(struct tpm_chip *chip)
{ {
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
unsigned long stop; unsigned long stop;
long ret; long ret;
struct st33zp24_dev *tpm_dev;
u8 data; u8 data;
if (check_locality(chip) == chip->vendor.locality) if (check_locality(chip) == tpm_dev->locality)
return chip->vendor.locality; return tpm_dev->locality;
tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
data = TPM_ACCESS_REQUEST_USE; data = TPM_ACCESS_REQUEST_USE;
ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1); ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
if (ret < 0) if (ret < 0)
return ret; return ret;
stop = jiffies + chip->vendor.timeout_a; stop = jiffies + chip->timeout_a;
/* Request locality is usually effective after the request */ /* Request locality is usually effective after the request */
do { do {
if (check_locality(chip) >= 0) if (check_locality(chip) >= 0)
return chip->vendor.locality; return tpm_dev->locality;
msleep(TPM_TIMEOUT); msleep(TPM_TIMEOUT);
} while (time_before(jiffies, stop)); } while (time_before(jiffies, stop));
...@@ -190,10 +174,9 @@ static int request_locality(struct tpm_chip *chip) ...@@ -190,10 +174,9 @@ static int request_locality(struct tpm_chip *chip)
*/ */
static void release_locality(struct tpm_chip *chip) static void release_locality(struct tpm_chip *chip)
{ {
struct st33zp24_dev *tpm_dev; struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
u8 data; u8 data;
tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
data = TPM_ACCESS_ACTIVE_LOCALITY; data = TPM_ACCESS_ACTIVE_LOCALITY;
tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1); tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
...@@ -206,23 +189,21 @@ static void release_locality(struct tpm_chip *chip) ...@@ -206,23 +189,21 @@ static void release_locality(struct tpm_chip *chip)
*/ */
static int get_burstcount(struct tpm_chip *chip) static int get_burstcount(struct tpm_chip *chip)
{ {
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
unsigned long stop; unsigned long stop;
int burstcnt, status; int burstcnt, status;
u8 tpm_reg, temp; u8 temp;
struct st33zp24_dev *tpm_dev;
tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
stop = jiffies + chip->vendor.timeout_d; stop = jiffies + chip->timeout_d;
do { do {
tpm_reg = TPM_STS + 1; status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS + 1,
status = tpm_dev->ops->recv(tpm_dev->phy_id, tpm_reg, &temp, 1); &temp, 1);
if (status < 0) if (status < 0)
return -EBUSY; return -EBUSY;
tpm_reg = TPM_STS + 2;
burstcnt = temp; burstcnt = temp;
status = tpm_dev->ops->recv(tpm_dev->phy_id, tpm_reg, &temp, 1); status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS + 2,
&temp, 1);
if (status < 0) if (status < 0)
return -EBUSY; return -EBUSY;
...@@ -271,15 +252,13 @@ static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, ...@@ -271,15 +252,13 @@ static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask,
static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
wait_queue_head_t *queue, bool check_cancel) wait_queue_head_t *queue, bool check_cancel)
{ {
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
unsigned long stop; unsigned long stop;
int ret = 0; int ret = 0;
bool canceled = false; bool canceled = false;
bool condition; bool condition;
u32 cur_intrs; u32 cur_intrs;
u8 status; u8 status;
struct st33zp24_dev *tpm_dev;
tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
/* check current status */ /* check current status */
status = st33zp24_status(chip); status = st33zp24_status(chip);
...@@ -288,10 +267,10 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, ...@@ -288,10 +267,10 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
stop = jiffies + timeout; stop = jiffies + timeout;
if (chip->vendor.irq) { if (chip->flags & TPM_CHIP_FLAG_IRQ) {
cur_intrs = tpm_dev->intrs; cur_intrs = tpm_dev->intrs;
clear_interruption(tpm_dev); clear_interruption(tpm_dev);
enable_irq(chip->vendor.irq); enable_irq(tpm_dev->irq);
do { do {
if (ret == -ERESTARTSYS && freezing(current)) if (ret == -ERESTARTSYS && freezing(current))
...@@ -314,7 +293,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, ...@@ -314,7 +293,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
} }
} while (ret == -ERESTARTSYS && freezing(current)); } while (ret == -ERESTARTSYS && freezing(current));
disable_irq_nosync(chip->vendor.irq); disable_irq_nosync(tpm_dev->irq);
} else { } else {
do { do {
...@@ -337,16 +316,14 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, ...@@ -337,16 +316,14 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
*/ */
static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) 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; int size = 0, burstcnt, len, ret;
struct st33zp24_dev *tpm_dev;
tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
while (size < count && while (size < count &&
wait_for_stat(chip, wait_for_stat(chip,
TPM_STS_DATA_AVAIL | TPM_STS_VALID, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
chip->vendor.timeout_c, chip->timeout_c,
&chip->vendor.read_queue, true) == 0) { &tpm_dev->read_queue, true) == 0) {
burstcnt = get_burstcount(chip); burstcnt = get_burstcount(chip);
if (burstcnt < 0) if (burstcnt < 0)
return burstcnt; return burstcnt;
...@@ -370,13 +347,11 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -370,13 +347,11 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id) static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id)
{ {
struct tpm_chip *chip = dev_id; struct tpm_chip *chip = dev_id;
struct st33zp24_dev *tpm_dev; struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
tpm_dev->intrs++; tpm_dev->intrs++;
wake_up_interruptible(&chip->vendor.read_queue); wake_up_interruptible(&tpm_dev->read_queue);
disable_irq_nosync(chip->vendor.irq); disable_irq_nosync(tpm_dev->irq);
return IRQ_HANDLED; return IRQ_HANDLED;
} /* tpm_ioserirq_handler() */ } /* tpm_ioserirq_handler() */
...@@ -393,19 +368,17 @@ static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id) ...@@ -393,19 +368,17 @@ static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id)
static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf, static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf,
size_t len) size_t len)
{ {
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
u32 status, i, size, ordinal; u32 status, i, size, ordinal;
int burstcnt = 0; int burstcnt = 0;
int ret; int ret;
u8 data; u8 data;
struct st33zp24_dev *tpm_dev;
if (!chip) if (!chip)
return -EBUSY; return -EBUSY;
if (len < TPM_HEADER_SIZE) if (len < TPM_HEADER_SIZE)
return -EBUSY; return -EBUSY;
tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
ret = request_locality(chip); ret = request_locality(chip);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -414,8 +387,8 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf, ...@@ -414,8 +387,8 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf,
if ((status & TPM_STS_COMMAND_READY) == 0) { if ((status & TPM_STS_COMMAND_READY) == 0) {
st33zp24_cancel(chip); st33zp24_cancel(chip);
if (wait_for_stat if (wait_for_stat
(chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, (chip, TPM_STS_COMMAND_READY, chip->timeout_b,
&chip->vendor.read_queue, false) < 0) { &tpm_dev->read_queue, false) < 0) {
ret = -ETIME; ret = -ETIME;
goto out_err; goto out_err;
} }
...@@ -456,12 +429,12 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf, ...@@ -456,12 +429,12 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf,
if (ret < 0) if (ret < 0)
goto out_err; goto out_err;
if (chip->vendor.irq) { if (chip->flags & TPM_CHIP_FLAG_IRQ) {
ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
ret = wait_for_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, ret = wait_for_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
tpm_calc_ordinal_duration(chip, ordinal), tpm_calc_ordinal_duration(chip, ordinal),
&chip->vendor.read_queue, false); &tpm_dev->read_queue, false);
if (ret < 0) if (ret < 0)
goto out_err; goto out_err;
} }
...@@ -532,6 +505,7 @@ static bool st33zp24_req_canceled(struct tpm_chip *chip, u8 status) ...@@ -532,6 +505,7 @@ static bool st33zp24_req_canceled(struct tpm_chip *chip, u8 status)
} }
static const struct tpm_class_ops st33zp24_tpm = { static const struct tpm_class_ops st33zp24_tpm = {
.flags = TPM_OPS_AUTO_STARTUP,
.send = st33zp24_send, .send = st33zp24_send,
.recv = st33zp24_recv, .recv = st33zp24_recv,
.cancel = st33zp24_cancel, .cancel = st33zp24_cancel,
...@@ -565,20 +539,20 @@ int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops, ...@@ -565,20 +539,20 @@ int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops,
if (!tpm_dev) if (!tpm_dev)
return -ENOMEM; return -ENOMEM;
TPM_VPRIV(chip) = tpm_dev;
tpm_dev->phy_id = phy_id; tpm_dev->phy_id = phy_id;
tpm_dev->ops = ops; tpm_dev->ops = ops;
dev_set_drvdata(&chip->dev, tpm_dev);
chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); chip->timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); chip->timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); chip->timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); chip->timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
chip->vendor.locality = LOCALITY0; tpm_dev->locality = LOCALITY0;
if (irq) { if (irq) {
/* INTERRUPT Setup */ /* INTERRUPT Setup */
init_waitqueue_head(&chip->vendor.read_queue); init_waitqueue_head(&tpm_dev->read_queue);
tpm_dev->intrs = 0; tpm_dev->intrs = 0;
if (request_locality(chip) != LOCALITY0) { if (request_locality(chip) != LOCALITY0) {
...@@ -611,16 +585,14 @@ int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops, ...@@ -611,16 +585,14 @@ int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops,
if (ret < 0) if (ret < 0)
goto _tpm_clean_answer; goto _tpm_clean_answer;
chip->vendor.irq = irq; tpm_dev->irq = irq;
chip->flags |= TPM_CHIP_FLAG_IRQ;
disable_irq_nosync(chip->vendor.irq); disable_irq_nosync(tpm_dev->irq);
tpm_gen_interrupt(chip); tpm_gen_interrupt(chip);
} }
tpm_get_timeouts(chip);
tpm_do_selftest(chip);
return tpm_chip_register(chip); return tpm_chip_register(chip);
_tpm_clean_answer: _tpm_clean_answer:
dev_info(&chip->dev, "TPM initialization fail\n"); dev_info(&chip->dev, "TPM initialization fail\n");
...@@ -650,10 +622,9 @@ EXPORT_SYMBOL(st33zp24_remove); ...@@ -650,10 +622,9 @@ EXPORT_SYMBOL(st33zp24_remove);
int st33zp24_pm_suspend(struct device *dev) int st33zp24_pm_suspend(struct device *dev)
{ {
struct tpm_chip *chip = dev_get_drvdata(dev); struct tpm_chip *chip = dev_get_drvdata(dev);
struct st33zp24_dev *tpm_dev; struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
int ret = 0;
tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip); int ret = 0;
if (gpio_is_valid(tpm_dev->io_lpcpd)) if (gpio_is_valid(tpm_dev->io_lpcpd))
gpio_set_value(tpm_dev->io_lpcpd, 0); gpio_set_value(tpm_dev->io_lpcpd, 0);
...@@ -672,16 +643,14 @@ EXPORT_SYMBOL(st33zp24_pm_suspend); ...@@ -672,16 +643,14 @@ EXPORT_SYMBOL(st33zp24_pm_suspend);
int st33zp24_pm_resume(struct device *dev) int st33zp24_pm_resume(struct device *dev)
{ {
struct tpm_chip *chip = dev_get_drvdata(dev); struct tpm_chip *chip = dev_get_drvdata(dev);
struct st33zp24_dev *tpm_dev; struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
int ret = 0; int ret = 0;
tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
if (gpio_is_valid(tpm_dev->io_lpcpd)) { if (gpio_is_valid(tpm_dev->io_lpcpd)) {
gpio_set_value(tpm_dev->io_lpcpd, 1); gpio_set_value(tpm_dev->io_lpcpd, 1);
ret = wait_for_stat(chip, ret = wait_for_stat(chip,
TPM_STS_VALID, chip->vendor.timeout_b, TPM_STS_VALID, chip->timeout_b,
&chip->vendor.read_queue, false); &tpm_dev->read_queue, false);
} else { } else {
ret = tpm_pm_resume(dev); ret = tpm_pm_resume(dev);
if (!ret) if (!ret)
......
/* /*
* STMicroelectronics TPM Linux driver for TPM ST33ZP24 * STMicroelectronics TPM Linux driver for TPM ST33ZP24
* Copyright (C) 2009 - 2015 STMicroelectronics * Copyright (C) 2009 - 2016 STMicroelectronics
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
...@@ -21,6 +21,18 @@ ...@@ -21,6 +21,18 @@
#define TPM_WRITE_DIRECTION 0x80 #define TPM_WRITE_DIRECTION 0x80
#define TPM_BUFSIZE 2048 #define TPM_BUFSIZE 2048
struct st33zp24_dev {
struct tpm_chip *chip;
void *phy_id;
const struct st33zp24_phy_ops *ops;
int locality;
int irq;
u32 intrs;
int io_lpcpd;
wait_queue_head_t read_queue;
};
struct st33zp24_phy_ops { struct st33zp24_phy_ops {
int (*send)(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size); int (*send)(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size);
int (*recv)(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size); int (*recv)(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size);
......
...@@ -29,33 +29,88 @@ ...@@ -29,33 +29,88 @@
#include "tpm.h" #include "tpm.h"
#include "tpm_eventlog.h" #include "tpm_eventlog.h"
static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); DEFINE_IDR(dev_nums_idr);
static LIST_HEAD(tpm_chip_list); static DEFINE_MUTEX(idr_lock);
static DEFINE_SPINLOCK(driver_lock);
struct class *tpm_class; struct class *tpm_class;
dev_t tpm_devt; dev_t tpm_devt;
/* /**
* tpm_chip_find_get - return tpm_chip for a given chip number * tpm_try_get_ops() - Get a ref to the tpm_chip
* @chip_num the device number for the chip * @chip: Chip to ref
*
* The caller must already have some kind of locking to ensure that chip is
* valid. This function will lock the chip so that the ops member can be
* accessed safely. The locking prevents tpm_chip_unregister from
* completing, so it should not be held for long periods.
*
* Returns -ERRNO if the chip could not be got.
*/ */
struct tpm_chip *tpm_chip_find_get(int chip_num) int tpm_try_get_ops(struct tpm_chip *chip)
{ {
struct tpm_chip *pos, *chip = NULL; int rc = -EIO;
rcu_read_lock(); get_device(&chip->dev);
list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num)
continue;
if (try_module_get(pos->pdev->driver->owner)) { down_read(&chip->ops_sem);
chip = pos; if (!chip->ops)
break; goto out_lock;
}
return 0;
out_lock:
up_read(&chip->ops_sem);
put_device(&chip->dev);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_try_get_ops);
/**
* tpm_put_ops() - Release a ref to the tpm_chip
* @chip: Chip to put
*
* This is the opposite pair to tpm_try_get_ops(). After this returns chip may
* be kfree'd.
*/
void tpm_put_ops(struct tpm_chip *chip)
{
up_read(&chip->ops_sem);
put_device(&chip->dev);
}
EXPORT_SYMBOL_GPL(tpm_put_ops);
/**
* tpm_chip_find_get() - return tpm_chip for a given chip number
* @chip_num: id to find
*
* The return'd chip has been tpm_try_get_ops'd and must be released via
* tpm_put_ops
*/
struct tpm_chip *tpm_chip_find_get(int chip_num)
{
struct tpm_chip *chip, *res = NULL;
int chip_prev;
mutex_lock(&idr_lock);
if (chip_num == TPM_ANY_NUM) {
chip_num = 0;
do {
chip_prev = chip_num;
chip = idr_get_next(&dev_nums_idr, &chip_num);
if (chip && !tpm_try_get_ops(chip)) {
res = chip;
break;
}
} while (chip_prev != chip_num);
} else {
chip = idr_find_slowpath(&dev_nums_idr, chip_num);
if (chip && !tpm_try_get_ops(chip))
res = chip;
} }
rcu_read_unlock();
return chip; mutex_unlock(&idr_lock);
return res;
} }
/** /**
...@@ -68,24 +123,25 @@ static void tpm_dev_release(struct device *dev) ...@@ -68,24 +123,25 @@ static void tpm_dev_release(struct device *dev)
{ {
struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev); struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
spin_lock(&driver_lock); mutex_lock(&idr_lock);
clear_bit(chip->dev_num, dev_mask); idr_remove(&dev_nums_idr, chip->dev_num);
spin_unlock(&driver_lock); mutex_unlock(&idr_lock);
kfree(chip); kfree(chip);
} }
/** /**
* tpmm_chip_alloc() - allocate a new struct tpm_chip instance * tpm_chip_alloc() - allocate a new struct tpm_chip instance
* @dev: device to which the chip is associated * @pdev: device to which the chip is associated
* At this point pdev mst be initialized, but does not have to
* be registered
* @ops: struct tpm_class_ops instance * @ops: struct tpm_class_ops instance
* *
* Allocates a new struct tpm_chip instance and assigns a free * Allocates a new struct tpm_chip instance and assigns a free
* device number for it. Caller does not have to worry about * device number for it. Must be paired with put_device(&chip->dev).
* freeing the allocated resources. When the devices is removed
* devres calls tpmm_chip_remove() to do the job.
*/ */
struct tpm_chip *tpmm_chip_alloc(struct device *dev, struct tpm_chip *tpm_chip_alloc(struct device *dev,
const struct tpm_class_ops *ops) const struct tpm_class_ops *ops)
{ {
struct tpm_chip *chip; struct tpm_chip *chip;
int rc; int rc;
...@@ -95,53 +151,75 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, ...@@ -95,53 +151,75 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
mutex_init(&chip->tpm_mutex); mutex_init(&chip->tpm_mutex);
INIT_LIST_HEAD(&chip->list); init_rwsem(&chip->ops_sem);
chip->ops = ops; chip->ops = ops;
spin_lock(&driver_lock); mutex_lock(&idr_lock);
chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES); rc = idr_alloc(&dev_nums_idr, NULL, 0, TPM_NUM_DEVICES, GFP_KERNEL);
spin_unlock(&driver_lock); mutex_unlock(&idr_lock);
if (rc < 0) {
if (chip->dev_num >= TPM_NUM_DEVICES) {
dev_err(dev, "No available tpm device numbers\n"); dev_err(dev, "No available tpm device numbers\n");
kfree(chip); kfree(chip);
return ERR_PTR(-ENOMEM); return ERR_PTR(rc);
} }
chip->dev_num = rc;
set_bit(chip->dev_num, dev_mask); device_initialize(&chip->dev);
scnprintf(chip->devname, sizeof(chip->devname), "tpm%d", chip->dev_num);
chip->pdev = dev;
dev_set_drvdata(dev, chip);
chip->dev.class = tpm_class; chip->dev.class = tpm_class;
chip->dev.release = tpm_dev_release; chip->dev.release = tpm_dev_release;
chip->dev.parent = chip->pdev; chip->dev.parent = dev;
#ifdef CONFIG_ACPI
chip->dev.groups = chip->groups; chip->dev.groups = chip->groups;
#endif
if (chip->dev_num == 0) if (chip->dev_num == 0)
chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR); chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
else else
chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num); chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num);
dev_set_name(&chip->dev, "%s", chip->devname); rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num);
if (rc)
goto out;
device_initialize(&chip->dev); if (!dev)
chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
cdev_init(&chip->cdev, &tpm_fops); cdev_init(&chip->cdev, &tpm_fops);
chip->cdev.owner = chip->pdev->driver->owner; chip->cdev.owner = THIS_MODULE;
chip->cdev.kobj.parent = &chip->dev.kobj; chip->cdev.kobj.parent = &chip->dev.kobj;
rc = devm_add_action(dev, (void (*)(void *)) put_device, &chip->dev); return chip;
if (rc) {
put_device(&chip->dev); out:
put_device(&chip->dev);
return ERR_PTR(rc);
}
EXPORT_SYMBOL_GPL(tpm_chip_alloc);
/**
* tpmm_chip_alloc() - allocate a new struct tpm_chip instance
* @pdev: parent device to which the chip is associated
* @ops: struct tpm_class_ops instance
*
* Same as tpm_chip_alloc except devm is used to do the put_device
*/
struct tpm_chip *tpmm_chip_alloc(struct device *pdev,
const struct tpm_class_ops *ops)
{
struct tpm_chip *chip;
int rc;
chip = tpm_chip_alloc(pdev, ops);
if (IS_ERR(chip))
return chip;
rc = devm_add_action_or_reset(pdev,
(void (*)(void *)) put_device,
&chip->dev);
if (rc)
return ERR_PTR(rc); return ERR_PTR(rc);
}
dev_set_drvdata(pdev, chip);
return chip; return chip;
} }
...@@ -155,7 +233,7 @@ static int tpm_add_char_device(struct tpm_chip *chip) ...@@ -155,7 +233,7 @@ static int tpm_add_char_device(struct tpm_chip *chip)
if (rc) { if (rc) {
dev_err(&chip->dev, dev_err(&chip->dev,
"unable to cdev_add() %s, major %d, minor %d, err=%d\n", "unable to cdev_add() %s, major %d, minor %d, err=%d\n",
chip->devname, MAJOR(chip->dev.devt), dev_name(&chip->dev), MAJOR(chip->dev.devt),
MINOR(chip->dev.devt), rc); MINOR(chip->dev.devt), rc);
return rc; return rc;
...@@ -165,13 +243,18 @@ static int tpm_add_char_device(struct tpm_chip *chip) ...@@ -165,13 +243,18 @@ static int tpm_add_char_device(struct tpm_chip *chip)
if (rc) { if (rc) {
dev_err(&chip->dev, dev_err(&chip->dev,
"unable to device_register() %s, major %d, minor %d, err=%d\n", "unable to device_register() %s, major %d, minor %d, err=%d\n",
chip->devname, MAJOR(chip->dev.devt), dev_name(&chip->dev), MAJOR(chip->dev.devt),
MINOR(chip->dev.devt), rc); MINOR(chip->dev.devt), rc);
cdev_del(&chip->cdev); cdev_del(&chip->cdev);
return rc; return rc;
} }
/* Make the chip available. */
mutex_lock(&idr_lock);
idr_replace(&dev_nums_idr, chip, chip->dev_num);
mutex_unlock(&idr_lock);
return rc; return rc;
} }
...@@ -179,20 +262,28 @@ static void tpm_del_char_device(struct tpm_chip *chip) ...@@ -179,20 +262,28 @@ static void tpm_del_char_device(struct tpm_chip *chip)
{ {
cdev_del(&chip->cdev); cdev_del(&chip->cdev);
device_del(&chip->dev); device_del(&chip->dev);
/* Make the chip unavailable. */
mutex_lock(&idr_lock);
idr_replace(&dev_nums_idr, NULL, chip->dev_num);
mutex_unlock(&idr_lock);
/* Make the driver uncallable. */
down_write(&chip->ops_sem);
if (chip->flags & TPM_CHIP_FLAG_TPM2)
tpm2_shutdown(chip, TPM2_SU_CLEAR);
chip->ops = NULL;
up_write(&chip->ops_sem);
} }
static int tpm1_chip_register(struct tpm_chip *chip) static int tpm1_chip_register(struct tpm_chip *chip)
{ {
int rc;
if (chip->flags & TPM_CHIP_FLAG_TPM2) if (chip->flags & TPM_CHIP_FLAG_TPM2)
return 0; return 0;
rc = tpm_sysfs_add_device(chip); tpm_sysfs_add_device(chip);
if (rc)
return rc;
chip->bios_dir = tpm_bios_log_setup(chip->devname); chip->bios_dir = tpm_bios_log_setup(dev_name(&chip->dev));
return 0; return 0;
} }
...@@ -204,10 +295,50 @@ static void tpm1_chip_unregister(struct tpm_chip *chip) ...@@ -204,10 +295,50 @@ static void tpm1_chip_unregister(struct tpm_chip *chip)
if (chip->bios_dir) if (chip->bios_dir)
tpm_bios_log_teardown(chip->bios_dir); tpm_bios_log_teardown(chip->bios_dir);
}
static void tpm_del_legacy_sysfs(struct tpm_chip *chip)
{
struct attribute **i;
if (chip->flags & (TPM_CHIP_FLAG_TPM2 | TPM_CHIP_FLAG_VIRTUAL))
return;
sysfs_remove_link(&chip->dev.parent->kobj, "ppi");
tpm_sysfs_del_device(chip); for (i = chip->groups[0]->attrs; *i != NULL; ++i)
sysfs_remove_link(&chip->dev.parent->kobj, (*i)->name);
} }
/* For compatibility with legacy sysfs paths we provide symlinks from the
* parent dev directory to selected names within the tpm chip directory. Old
* kernel versions created these files directly under the parent.
*/
static int tpm_add_legacy_sysfs(struct tpm_chip *chip)
{
struct attribute **i;
int rc;
if (chip->flags & (TPM_CHIP_FLAG_TPM2 | TPM_CHIP_FLAG_VIRTUAL))
return 0;
rc = __compat_only_sysfs_link_entry_to_kobj(
&chip->dev.parent->kobj, &chip->dev.kobj, "ppi");
if (rc && rc != -ENOENT)
return rc;
/* All the names from tpm-sysfs */
for (i = chip->groups[0]->attrs; *i != NULL; ++i) {
rc = __compat_only_sysfs_link_entry_to_kobj(
&chip->dev.parent->kobj, &chip->dev.kobj, (*i)->name);
if (rc) {
tpm_del_legacy_sysfs(chip);
return rc;
}
}
return 0;
}
/* /*
* tpm_chip_register() - create a character device for the TPM chip * tpm_chip_register() - create a character device for the TPM chip
* @chip: TPM chip to use. * @chip: TPM chip to use.
...@@ -223,6 +354,15 @@ int tpm_chip_register(struct tpm_chip *chip) ...@@ -223,6 +354,15 @@ int tpm_chip_register(struct tpm_chip *chip)
{ {
int rc; int rc;
if (chip->ops->flags & TPM_OPS_AUTO_STARTUP) {
if (chip->flags & TPM_CHIP_FLAG_TPM2)
rc = tpm2_auto_startup(chip);
else
rc = tpm1_auto_startup(chip);
if (rc)
return rc;
}
rc = tpm1_chip_register(chip); rc = tpm1_chip_register(chip);
if (rc) if (rc)
return rc; return rc;
...@@ -230,30 +370,20 @@ int tpm_chip_register(struct tpm_chip *chip) ...@@ -230,30 +370,20 @@ int tpm_chip_register(struct tpm_chip *chip)
tpm_add_ppi(chip); tpm_add_ppi(chip);
rc = tpm_add_char_device(chip); rc = tpm_add_char_device(chip);
if (rc) if (rc) {
goto out_err; tpm1_chip_unregister(chip);
return rc;
/* Make the chip available. */ }
spin_lock(&driver_lock);
list_add_tail_rcu(&chip->list, &tpm_chip_list);
spin_unlock(&driver_lock);
chip->flags |= TPM_CHIP_FLAG_REGISTERED; chip->flags |= TPM_CHIP_FLAG_REGISTERED;
if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) { rc = tpm_add_legacy_sysfs(chip);
rc = __compat_only_sysfs_link_entry_to_kobj(&chip->pdev->kobj, if (rc) {
&chip->dev.kobj, tpm_chip_unregister(chip);
"ppi"); return rc;
if (rc && rc != -ENOENT) {
tpm_chip_unregister(chip);
return rc;
}
} }
return 0; return 0;
out_err:
tpm1_chip_unregister(chip);
return rc;
} }
EXPORT_SYMBOL_GPL(tpm_chip_register); EXPORT_SYMBOL_GPL(tpm_chip_register);
...@@ -264,6 +394,9 @@ EXPORT_SYMBOL_GPL(tpm_chip_register); ...@@ -264,6 +394,9 @@ EXPORT_SYMBOL_GPL(tpm_chip_register);
* Takes the chip first away from the list of available TPM chips and then * Takes the chip first away from the list of available TPM chips and then
* cleans up all the resources reserved by tpm_chip_register(). * cleans up all the resources reserved by tpm_chip_register().
* *
* Once this function returns the driver call backs in 'op's will not be
* running and will no longer start.
*
* NOTE: This function should be only called before deinitializing chip * NOTE: This function should be only called before deinitializing chip
* resources. * resources.
*/ */
...@@ -272,13 +405,7 @@ void tpm_chip_unregister(struct tpm_chip *chip) ...@@ -272,13 +405,7 @@ void tpm_chip_unregister(struct tpm_chip *chip)
if (!(chip->flags & TPM_CHIP_FLAG_REGISTERED)) if (!(chip->flags & TPM_CHIP_FLAG_REGISTERED))
return; return;
spin_lock(&driver_lock); tpm_del_legacy_sysfs(chip);
list_del_rcu(&chip->list);
spin_unlock(&driver_lock);
synchronize_rcu();
if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
sysfs_remove_link(&chip->pdev->kobj, "ppi");
tpm1_chip_unregister(chip); tpm1_chip_unregister(chip);
tpm_del_char_device(chip); tpm_del_char_device(chip);
......
...@@ -61,7 +61,7 @@ static int tpm_open(struct inode *inode, struct file *file) ...@@ -61,7 +61,7 @@ static int tpm_open(struct inode *inode, struct file *file)
* by the check of is_open variable, which is protected * by the check of is_open variable, which is protected
* by driver_lock. */ * by driver_lock. */
if (test_and_set_bit(0, &chip->is_open)) { if (test_and_set_bit(0, &chip->is_open)) {
dev_dbg(chip->pdev, "Another process owns this TPM\n"); dev_dbg(&chip->dev, "Another process owns this TPM\n");
return -EBUSY; return -EBUSY;
} }
...@@ -79,7 +79,6 @@ static int tpm_open(struct inode *inode, struct file *file) ...@@ -79,7 +79,6 @@ static int tpm_open(struct inode *inode, struct file *file)
INIT_WORK(&priv->work, timeout_work); INIT_WORK(&priv->work, timeout_work);
file->private_data = priv; file->private_data = priv;
get_device(chip->pdev);
return 0; return 0;
} }
...@@ -137,9 +136,18 @@ static ssize_t tpm_write(struct file *file, const char __user *buf, ...@@ -137,9 +136,18 @@ static ssize_t tpm_write(struct file *file, const char __user *buf,
return -EFAULT; return -EFAULT;
} }
/* atomic tpm command send and result receive */ /* atomic tpm command send and result receive. We only hold the ops
* lock during this period so that the tpm can be unregistered even if
* the char dev is held open.
*/
if (tpm_try_get_ops(priv->chip)) {
mutex_unlock(&priv->buffer_mutex);
return -EPIPE;
}
out_size = tpm_transmit(priv->chip, priv->data_buffer, out_size = tpm_transmit(priv->chip, priv->data_buffer,
sizeof(priv->data_buffer)); sizeof(priv->data_buffer));
tpm_put_ops(priv->chip);
if (out_size < 0) { if (out_size < 0) {
mutex_unlock(&priv->buffer_mutex); mutex_unlock(&priv->buffer_mutex);
return out_size; return out_size;
...@@ -166,7 +174,6 @@ static int tpm_release(struct inode *inode, struct file *file) ...@@ -166,7 +174,6 @@ static int tpm_release(struct inode *inode, struct file *file)
file->private_data = NULL; file->private_data = NULL;
atomic_set(&priv->data_pending, 0); atomic_set(&priv->data_pending, 0);
clear_bit(0, &priv->chip->is_open); clear_bit(0, &priv->chip->is_open);
put_device(priv->chip->pdev);
kfree(priv); kfree(priv);
return 0; return 0;
} }
......
...@@ -319,7 +319,7 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, ...@@ -319,7 +319,7 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
duration_idx = tpm_ordinal_duration[ordinal]; duration_idx = tpm_ordinal_duration[ordinal];
if (duration_idx != TPM_UNDEFINED) if (duration_idx != TPM_UNDEFINED)
duration = chip->vendor.duration[duration_idx]; duration = chip->duration[duration_idx];
if (duration <= 0) if (duration <= 0)
return 2 * 60 * HZ; return 2 * 60 * HZ;
else else
...@@ -345,7 +345,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, ...@@ -345,7 +345,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
if (count == 0) if (count == 0)
return -ENODATA; return -ENODATA;
if (count > bufsiz) { if (count > bufsiz) {
dev_err(chip->pdev, dev_err(&chip->dev,
"invalid count value %x %zx\n", count, bufsiz); "invalid count value %x %zx\n", count, bufsiz);
return -E2BIG; return -E2BIG;
} }
...@@ -354,12 +354,12 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, ...@@ -354,12 +354,12 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
rc = chip->ops->send(chip, (u8 *) buf, count); rc = chip->ops->send(chip, (u8 *) buf, count);
if (rc < 0) { if (rc < 0) {
dev_err(chip->pdev, dev_err(&chip->dev,
"tpm_transmit: tpm_send: error %zd\n", rc); "tpm_transmit: tpm_send: error %zd\n", rc);
goto out; goto out;
} }
if (chip->vendor.irq) if (chip->flags & TPM_CHIP_FLAG_IRQ)
goto out_recv; goto out_recv;
if (chip->flags & TPM_CHIP_FLAG_TPM2) if (chip->flags & TPM_CHIP_FLAG_TPM2)
...@@ -373,7 +373,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, ...@@ -373,7 +373,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
goto out_recv; goto out_recv;
if (chip->ops->req_canceled(chip, status)) { if (chip->ops->req_canceled(chip, status)) {
dev_err(chip->pdev, "Operation Canceled\n"); dev_err(&chip->dev, "Operation Canceled\n");
rc = -ECANCELED; rc = -ECANCELED;
goto out; goto out;
} }
...@@ -383,14 +383,14 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, ...@@ -383,14 +383,14 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
} while (time_before(jiffies, stop)); } while (time_before(jiffies, stop));
chip->ops->cancel(chip); chip->ops->cancel(chip);
dev_err(chip->pdev, "Operation Timed out\n"); dev_err(&chip->dev, "Operation Timed out\n");
rc = -ETIME; rc = -ETIME;
goto out; goto out;
out_recv: out_recv:
rc = chip->ops->recv(chip, (u8 *) buf, bufsiz); rc = chip->ops->recv(chip, (u8 *) buf, bufsiz);
if (rc < 0) if (rc < 0)
dev_err(chip->pdev, dev_err(&chip->dev,
"tpm_transmit: tpm_recv: error %zd\n", rc); "tpm_transmit: tpm_recv: error %zd\n", rc);
out: out:
mutex_unlock(&chip->tpm_mutex); mutex_unlock(&chip->tpm_mutex);
...@@ -416,7 +416,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd, ...@@ -416,7 +416,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd,
err = be32_to_cpu(header->return_code); err = be32_to_cpu(header->return_code);
if (err != 0 && desc) if (err != 0 && desc)
dev_err(chip->pdev, "A TPM error (%d) occurred %s\n", err, dev_err(&chip->dev, "A TPM error (%d) occurred %s\n", err,
desc); desc);
return err; return err;
...@@ -432,12 +432,11 @@ static const struct tpm_input_header tpm_getcap_header = { ...@@ -432,12 +432,11 @@ static const struct tpm_input_header tpm_getcap_header = {
.ordinal = TPM_ORD_GET_CAP .ordinal = TPM_ORD_GET_CAP
}; };
ssize_t tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap, ssize_t tpm_getcap(struct tpm_chip *chip, __be32 subcap_id, cap_t *cap,
const char *desc) const char *desc)
{ {
struct tpm_cmd_t tpm_cmd; struct tpm_cmd_t tpm_cmd;
int rc; int rc;
struct tpm_chip *chip = dev_get_drvdata(dev);
tpm_cmd.header.in = tpm_getcap_header; tpm_cmd.header.in = tpm_getcap_header;
if (subcap_id == CAP_VERSION_1_1 || subcap_id == CAP_VERSION_1_2) { if (subcap_id == CAP_VERSION_1_1 || subcap_id == CAP_VERSION_1_2) {
...@@ -505,15 +504,15 @@ int tpm_get_timeouts(struct tpm_chip *chip) ...@@ -505,15 +504,15 @@ int tpm_get_timeouts(struct tpm_chip *chip)
if (chip->flags & TPM_CHIP_FLAG_TPM2) { if (chip->flags & TPM_CHIP_FLAG_TPM2) {
/* Fixed timeouts for TPM2 */ /* Fixed timeouts for TPM2 */
chip->vendor.timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A); chip->timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A);
chip->vendor.timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B); chip->timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B);
chip->vendor.timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C); chip->timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C);
chip->vendor.timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D); chip->timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D);
chip->vendor.duration[TPM_SHORT] = chip->duration[TPM_SHORT] =
msecs_to_jiffies(TPM2_DURATION_SHORT); msecs_to_jiffies(TPM2_DURATION_SHORT);
chip->vendor.duration[TPM_MEDIUM] = chip->duration[TPM_MEDIUM] =
msecs_to_jiffies(TPM2_DURATION_MEDIUM); msecs_to_jiffies(TPM2_DURATION_MEDIUM);
chip->vendor.duration[TPM_LONG] = chip->duration[TPM_LONG] =
msecs_to_jiffies(TPM2_DURATION_LONG); msecs_to_jiffies(TPM2_DURATION_LONG);
return 0; return 0;
} }
...@@ -527,7 +526,7 @@ int tpm_get_timeouts(struct tpm_chip *chip) ...@@ -527,7 +526,7 @@ int tpm_get_timeouts(struct tpm_chip *chip)
if (rc == TPM_ERR_INVALID_POSTINIT) { if (rc == TPM_ERR_INVALID_POSTINIT) {
/* The TPM is not started, we are the first to talk to it. /* The TPM is not started, we are the first to talk to it.
Execute a startup command. */ Execute a startup command. */
dev_info(chip->pdev, "Issuing TPM_STARTUP"); dev_info(&chip->dev, "Issuing TPM_STARTUP");
if (tpm_startup(chip, TPM_ST_CLEAR)) if (tpm_startup(chip, TPM_ST_CLEAR))
return rc; return rc;
...@@ -539,7 +538,7 @@ int tpm_get_timeouts(struct tpm_chip *chip) ...@@ -539,7 +538,7 @@ int tpm_get_timeouts(struct tpm_chip *chip)
NULL); NULL);
} }
if (rc) { if (rc) {
dev_err(chip->pdev, dev_err(&chip->dev,
"A TPM error (%zd) occurred attempting to determine the timeouts\n", "A TPM error (%zd) occurred attempting to determine the timeouts\n",
rc); rc);
goto duration; goto duration;
...@@ -561,10 +560,10 @@ int tpm_get_timeouts(struct tpm_chip *chip) ...@@ -561,10 +560,10 @@ int tpm_get_timeouts(struct tpm_chip *chip)
* of misreporting. * of misreporting.
*/ */
if (chip->ops->update_timeouts != NULL) if (chip->ops->update_timeouts != NULL)
chip->vendor.timeout_adjusted = chip->timeout_adjusted =
chip->ops->update_timeouts(chip, new_timeout); chip->ops->update_timeouts(chip, new_timeout);
if (!chip->vendor.timeout_adjusted) { if (!chip->timeout_adjusted) {
/* Don't overwrite default if value is 0 */ /* Don't overwrite default if value is 0 */
if (new_timeout[0] != 0 && new_timeout[0] < 1000) { if (new_timeout[0] != 0 && new_timeout[0] < 1000) {
int i; int i;
...@@ -572,13 +571,13 @@ int tpm_get_timeouts(struct tpm_chip *chip) ...@@ -572,13 +571,13 @@ int tpm_get_timeouts(struct tpm_chip *chip)
/* timeouts in msec rather usec */ /* timeouts in msec rather usec */
for (i = 0; i != ARRAY_SIZE(new_timeout); i++) for (i = 0; i != ARRAY_SIZE(new_timeout); i++)
new_timeout[i] *= 1000; new_timeout[i] *= 1000;
chip->vendor.timeout_adjusted = true; chip->timeout_adjusted = true;
} }
} }
/* Report adjusted timeouts */ /* Report adjusted timeouts */
if (chip->vendor.timeout_adjusted) { if (chip->timeout_adjusted) {
dev_info(chip->pdev, dev_info(&chip->dev,
HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n", HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n",
old_timeout[0], new_timeout[0], old_timeout[0], new_timeout[0],
old_timeout[1], new_timeout[1], old_timeout[1], new_timeout[1],
...@@ -586,10 +585,10 @@ int tpm_get_timeouts(struct tpm_chip *chip) ...@@ -586,10 +585,10 @@ int tpm_get_timeouts(struct tpm_chip *chip)
old_timeout[3], new_timeout[3]); old_timeout[3], new_timeout[3]);
} }
chip->vendor.timeout_a = usecs_to_jiffies(new_timeout[0]); chip->timeout_a = usecs_to_jiffies(new_timeout[0]);
chip->vendor.timeout_b = usecs_to_jiffies(new_timeout[1]); chip->timeout_b = usecs_to_jiffies(new_timeout[1]);
chip->vendor.timeout_c = usecs_to_jiffies(new_timeout[2]); chip->timeout_c = usecs_to_jiffies(new_timeout[2]);
chip->vendor.timeout_d = usecs_to_jiffies(new_timeout[3]); chip->timeout_d = usecs_to_jiffies(new_timeout[3]);
duration: duration:
tpm_cmd.header.in = tpm_getcap_header; tpm_cmd.header.in = tpm_getcap_header;
...@@ -608,11 +607,11 @@ int tpm_get_timeouts(struct tpm_chip *chip) ...@@ -608,11 +607,11 @@ int tpm_get_timeouts(struct tpm_chip *chip)
return -EINVAL; return -EINVAL;
duration_cap = &tpm_cmd.params.getcap_out.cap.duration; duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
chip->vendor.duration[TPM_SHORT] = chip->duration[TPM_SHORT] =
usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short)); usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short));
chip->vendor.duration[TPM_MEDIUM] = chip->duration[TPM_MEDIUM] =
usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium)); usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium));
chip->vendor.duration[TPM_LONG] = chip->duration[TPM_LONG] =
usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long)); usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long));
/* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
...@@ -620,12 +619,12 @@ int tpm_get_timeouts(struct tpm_chip *chip) ...@@ -620,12 +619,12 @@ int tpm_get_timeouts(struct tpm_chip *chip)
* fix up the resulting too-small TPM_SHORT value to make things work. * fix up the resulting too-small TPM_SHORT value to make things work.
* We also scale the TPM_MEDIUM and -_LONG values by 1000. * We also scale the TPM_MEDIUM and -_LONG values by 1000.
*/ */
if (chip->vendor.duration[TPM_SHORT] < (HZ / 100)) { if (chip->duration[TPM_SHORT] < (HZ / 100)) {
chip->vendor.duration[TPM_SHORT] = HZ; chip->duration[TPM_SHORT] = HZ;
chip->vendor.duration[TPM_MEDIUM] *= 1000; chip->duration[TPM_MEDIUM] *= 1000;
chip->vendor.duration[TPM_LONG] *= 1000; chip->duration[TPM_LONG] *= 1000;
chip->vendor.duration_adjusted = true; chip->duration_adjusted = true;
dev_info(chip->pdev, "Adjusting TPM timeout parameters."); dev_info(&chip->dev, "Adjusting TPM timeout parameters.");
} }
return 0; return 0;
} }
...@@ -700,7 +699,7 @@ int tpm_is_tpm2(u32 chip_num) ...@@ -700,7 +699,7 @@ int tpm_is_tpm2(u32 chip_num)
rc = (chip->flags & TPM_CHIP_FLAG_TPM2) != 0; rc = (chip->flags & TPM_CHIP_FLAG_TPM2) != 0;
tpm_chip_put(chip); tpm_put_ops(chip);
return rc; return rc;
} }
...@@ -729,7 +728,7 @@ int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) ...@@ -729,7 +728,7 @@ int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf)
rc = tpm2_pcr_read(chip, pcr_idx, res_buf); rc = tpm2_pcr_read(chip, pcr_idx, res_buf);
else else
rc = tpm_pcr_read_dev(chip, pcr_idx, res_buf); rc = tpm_pcr_read_dev(chip, pcr_idx, res_buf);
tpm_chip_put(chip); tpm_put_ops(chip);
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(tpm_pcr_read); EXPORT_SYMBOL_GPL(tpm_pcr_read);
...@@ -764,7 +763,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) ...@@ -764,7 +763,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
if (chip->flags & TPM_CHIP_FLAG_TPM2) { if (chip->flags & TPM_CHIP_FLAG_TPM2) {
rc = tpm2_pcr_extend(chip, pcr_idx, hash); rc = tpm2_pcr_extend(chip, pcr_idx, hash);
tpm_chip_put(chip); tpm_put_ops(chip);
return rc; return rc;
} }
...@@ -774,7 +773,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) ...@@ -774,7 +773,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
"attempting extend a PCR value"); "attempting extend a PCR value");
tpm_chip_put(chip); tpm_put_ops(chip);
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(tpm_pcr_extend); EXPORT_SYMBOL_GPL(tpm_pcr_extend);
...@@ -815,7 +814,9 @@ int tpm_do_selftest(struct tpm_chip *chip) ...@@ -815,7 +814,9 @@ int tpm_do_selftest(struct tpm_chip *chip)
* around 300ms while the self test is ongoing, keep trying * around 300ms while the self test is ongoing, keep trying
* until the self test duration expires. */ * until the self test duration expires. */
if (rc == -ETIME) { if (rc == -ETIME) {
dev_info(chip->pdev, HW_ERR "TPM command timed out during continue self test"); dev_info(
&chip->dev, HW_ERR
"TPM command timed out during continue self test");
msleep(delay_msec); msleep(delay_msec);
continue; continue;
} }
...@@ -825,7 +826,7 @@ int tpm_do_selftest(struct tpm_chip *chip) ...@@ -825,7 +826,7 @@ int tpm_do_selftest(struct tpm_chip *chip)
rc = be32_to_cpu(cmd.header.out.return_code); rc = be32_to_cpu(cmd.header.out.return_code);
if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) { if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) {
dev_info(chip->pdev, dev_info(&chip->dev,
"TPM is disabled/deactivated (0x%X)\n", rc); "TPM is disabled/deactivated (0x%X)\n", rc);
/* TPM is disabled and/or deactivated; driver can /* TPM is disabled and/or deactivated; driver can
* proceed and TPM does handle commands for * proceed and TPM does handle commands for
...@@ -842,6 +843,33 @@ int tpm_do_selftest(struct tpm_chip *chip) ...@@ -842,6 +843,33 @@ int tpm_do_selftest(struct tpm_chip *chip)
} }
EXPORT_SYMBOL_GPL(tpm_do_selftest); EXPORT_SYMBOL_GPL(tpm_do_selftest);
/**
* tpm1_auto_startup - Perform the standard automatic TPM initialization
* sequence
* @chip: TPM chip to use
*
* Returns 0 on success, < 0 in case of fatal error.
*/
int tpm1_auto_startup(struct tpm_chip *chip)
{
int rc;
rc = tpm_get_timeouts(chip);
if (rc)
goto out;
rc = tpm_do_selftest(chip);
if (rc) {
dev_err(&chip->dev, "TPM self test failed\n");
goto out;
}
return rc;
out:
if (rc > 0)
rc = -ENODEV;
return rc;
}
int tpm_send(u32 chip_num, void *cmd, size_t buflen) int tpm_send(u32 chip_num, void *cmd, size_t buflen)
{ {
struct tpm_chip *chip; struct tpm_chip *chip;
...@@ -853,7 +881,7 @@ int tpm_send(u32 chip_num, void *cmd, size_t buflen) ...@@ -853,7 +881,7 @@ int tpm_send(u32 chip_num, void *cmd, size_t buflen)
rc = tpm_transmit_cmd(chip, cmd, buflen, "attempting tpm_cmd"); rc = tpm_transmit_cmd(chip, cmd, buflen, "attempting tpm_cmd");
tpm_chip_put(chip); tpm_put_ops(chip);
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(tpm_send); EXPORT_SYMBOL_GPL(tpm_send);
...@@ -888,7 +916,7 @@ int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, ...@@ -888,7 +916,7 @@ int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
stop = jiffies + timeout; stop = jiffies + timeout;
if (chip->vendor.irq) { if (chip->flags & TPM_CHIP_FLAG_IRQ) {
again: again:
timeout = stop - jiffies; timeout = stop - jiffies;
if ((long)timeout <= 0) if ((long)timeout <= 0)
...@@ -978,10 +1006,10 @@ int tpm_pm_suspend(struct device *dev) ...@@ -978,10 +1006,10 @@ int tpm_pm_suspend(struct device *dev)
} }
if (rc) if (rc)
dev_err(chip->pdev, dev_err(&chip->dev,
"Error (%d) sending savestate before suspend\n", rc); "Error (%d) sending savestate before suspend\n", rc);
else if (try > 0) else if (try > 0)
dev_warn(chip->pdev, "TPM savestate took %dms\n", dev_warn(&chip->dev, "TPM savestate took %dms\n",
try * TPM_TIMEOUT_RETRY); try * TPM_TIMEOUT_RETRY);
return rc; return rc;
...@@ -1035,7 +1063,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) ...@@ -1035,7 +1063,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
if (chip->flags & TPM_CHIP_FLAG_TPM2) { if (chip->flags & TPM_CHIP_FLAG_TPM2) {
err = tpm2_get_random(chip, out, max); err = tpm2_get_random(chip, out, max);
tpm_chip_put(chip); tpm_put_ops(chip);
return err; return err;
} }
...@@ -1057,7 +1085,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) ...@@ -1057,7 +1085,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
num_bytes -= recd; num_bytes -= recd;
} while (retries-- && total < max); } while (retries-- && total < max);
tpm_chip_put(chip); tpm_put_ops(chip);
return total ? total : -EIO; return total ? total : -EIO;
} }
EXPORT_SYMBOL_GPL(tpm_get_random); EXPORT_SYMBOL_GPL(tpm_get_random);
...@@ -1083,7 +1111,7 @@ int tpm_seal_trusted(u32 chip_num, struct trusted_key_payload *payload, ...@@ -1083,7 +1111,7 @@ int tpm_seal_trusted(u32 chip_num, struct trusted_key_payload *payload,
rc = tpm2_seal_trusted(chip, payload, options); rc = tpm2_seal_trusted(chip, payload, options);
tpm_chip_put(chip); tpm_put_ops(chip);
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(tpm_seal_trusted); EXPORT_SYMBOL_GPL(tpm_seal_trusted);
...@@ -1109,7 +1137,8 @@ int tpm_unseal_trusted(u32 chip_num, struct trusted_key_payload *payload, ...@@ -1109,7 +1137,8 @@ int tpm_unseal_trusted(u32 chip_num, struct trusted_key_payload *payload,
rc = tpm2_unseal_trusted(chip, payload, options); rc = tpm2_unseal_trusted(chip, payload, options);
tpm_chip_put(chip); tpm_put_ops(chip);
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(tpm_unseal_trusted); EXPORT_SYMBOL_GPL(tpm_unseal_trusted);
...@@ -1136,6 +1165,7 @@ static int __init tpm_init(void) ...@@ -1136,6 +1165,7 @@ static int __init tpm_init(void)
static void __exit tpm_exit(void) static void __exit tpm_exit(void)
{ {
idr_destroy(&dev_nums_idr);
class_destroy(tpm_class); class_destroy(tpm_class);
unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES); unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES);
} }
......
...@@ -36,7 +36,7 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, ...@@ -36,7 +36,7 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
int i, rc; int i, rc;
char *str = buf; char *str = buf;
struct tpm_chip *chip = dev_get_drvdata(dev); struct tpm_chip *chip = to_tpm_chip(dev);
tpm_cmd.header.in = tpm_readpubek_header; tpm_cmd.header.in = tpm_readpubek_header;
err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
...@@ -92,9 +92,9 @@ static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr, ...@@ -92,9 +92,9 @@ static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr,
ssize_t rc; ssize_t rc;
int i, j, num_pcrs; int i, j, num_pcrs;
char *str = buf; char *str = buf;
struct tpm_chip *chip = dev_get_drvdata(dev); struct tpm_chip *chip = to_tpm_chip(dev);
rc = tpm_getcap(dev, TPM_CAP_PROP_PCR, &cap, rc = tpm_getcap(chip, TPM_CAP_PROP_PCR, &cap,
"attempting to determine the number of PCRS"); "attempting to determine the number of PCRS");
if (rc) if (rc)
return 0; return 0;
...@@ -119,8 +119,8 @@ static ssize_t enabled_show(struct device *dev, struct device_attribute *attr, ...@@ -119,8 +119,8 @@ static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
cap_t cap; cap_t cap;
ssize_t rc; ssize_t rc;
rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap, rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap,
"attempting to determine the permanent enabled state"); "attempting to determine the permanent enabled state");
if (rc) if (rc)
return 0; return 0;
...@@ -135,8 +135,8 @@ static ssize_t active_show(struct device *dev, struct device_attribute *attr, ...@@ -135,8 +135,8 @@ static ssize_t active_show(struct device *dev, struct device_attribute *attr,
cap_t cap; cap_t cap;
ssize_t rc; ssize_t rc;
rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap, rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap,
"attempting to determine the permanent active state"); "attempting to determine the permanent active state");
if (rc) if (rc)
return 0; return 0;
...@@ -151,8 +151,8 @@ static ssize_t owned_show(struct device *dev, struct device_attribute *attr, ...@@ -151,8 +151,8 @@ static ssize_t owned_show(struct device *dev, struct device_attribute *attr,
cap_t cap; cap_t cap;
ssize_t rc; ssize_t rc;
rc = tpm_getcap(dev, TPM_CAP_PROP_OWNER, &cap, rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_PROP_OWNER, &cap,
"attempting to determine the owner state"); "attempting to determine the owner state");
if (rc) if (rc)
return 0; return 0;
...@@ -167,8 +167,8 @@ static ssize_t temp_deactivated_show(struct device *dev, ...@@ -167,8 +167,8 @@ static ssize_t temp_deactivated_show(struct device *dev,
cap_t cap; cap_t cap;
ssize_t rc; ssize_t rc;
rc = tpm_getcap(dev, TPM_CAP_FLAG_VOL, &cap, rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_VOL, &cap,
"attempting to determine the temporary state"); "attempting to determine the temporary state");
if (rc) if (rc)
return 0; return 0;
...@@ -180,11 +180,12 @@ static DEVICE_ATTR_RO(temp_deactivated); ...@@ -180,11 +180,12 @@ static DEVICE_ATTR_RO(temp_deactivated);
static ssize_t caps_show(struct device *dev, struct device_attribute *attr, static ssize_t caps_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct tpm_chip *chip = to_tpm_chip(dev);
cap_t cap; cap_t cap;
ssize_t rc; ssize_t rc;
char *str = buf; char *str = buf;
rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap, rc = tpm_getcap(chip, TPM_CAP_PROP_MANUFACTURER, &cap,
"attempting to determine the manufacturer"); "attempting to determine the manufacturer");
if (rc) if (rc)
return 0; return 0;
...@@ -192,8 +193,8 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr, ...@@ -192,8 +193,8 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr,
be32_to_cpu(cap.manufacturer_id)); be32_to_cpu(cap.manufacturer_id));
/* Try to get a TPM version 1.2 TPM_CAP_VERSION_INFO */ /* Try to get a TPM version 1.2 TPM_CAP_VERSION_INFO */
rc = tpm_getcap(dev, CAP_VERSION_1_2, &cap, rc = tpm_getcap(chip, CAP_VERSION_1_2, &cap,
"attempting to determine the 1.2 version"); "attempting to determine the 1.2 version");
if (!rc) { if (!rc) {
str += sprintf(str, str += sprintf(str,
"TCG version: %d.%d\nFirmware version: %d.%d\n", "TCG version: %d.%d\nFirmware version: %d.%d\n",
...@@ -203,7 +204,7 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr, ...@@ -203,7 +204,7 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr,
cap.tpm_version_1_2.revMinor); cap.tpm_version_1_2.revMinor);
} else { } else {
/* Otherwise just use TPM_STRUCT_VER */ /* Otherwise just use TPM_STRUCT_VER */
rc = tpm_getcap(dev, CAP_VERSION_1_1, &cap, rc = tpm_getcap(chip, CAP_VERSION_1_1, &cap,
"attempting to determine the 1.1 version"); "attempting to determine the 1.1 version");
if (rc) if (rc)
return 0; return 0;
...@@ -222,7 +223,7 @@ static DEVICE_ATTR_RO(caps); ...@@ -222,7 +223,7 @@ static DEVICE_ATTR_RO(caps);
static ssize_t cancel_store(struct device *dev, struct device_attribute *attr, static ssize_t cancel_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct tpm_chip *chip = dev_get_drvdata(dev); struct tpm_chip *chip = to_tpm_chip(dev);
if (chip == NULL) if (chip == NULL)
return 0; return 0;
...@@ -234,16 +235,16 @@ static DEVICE_ATTR_WO(cancel); ...@@ -234,16 +235,16 @@ static DEVICE_ATTR_WO(cancel);
static ssize_t durations_show(struct device *dev, struct device_attribute *attr, static ssize_t durations_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct tpm_chip *chip = dev_get_drvdata(dev); struct tpm_chip *chip = to_tpm_chip(dev);
if (chip->vendor.duration[TPM_LONG] == 0) if (chip->duration[TPM_LONG] == 0)
return 0; return 0;
return sprintf(buf, "%d %d %d [%s]\n", return sprintf(buf, "%d %d %d [%s]\n",
jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]), jiffies_to_usecs(chip->duration[TPM_SHORT]),
jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]), jiffies_to_usecs(chip->duration[TPM_MEDIUM]),
jiffies_to_usecs(chip->vendor.duration[TPM_LONG]), jiffies_to_usecs(chip->duration[TPM_LONG]),
chip->vendor.duration_adjusted chip->duration_adjusted
? "adjusted" : "original"); ? "adjusted" : "original");
} }
static DEVICE_ATTR_RO(durations); static DEVICE_ATTR_RO(durations);
...@@ -251,14 +252,14 @@ static DEVICE_ATTR_RO(durations); ...@@ -251,14 +252,14 @@ static DEVICE_ATTR_RO(durations);
static ssize_t timeouts_show(struct device *dev, struct device_attribute *attr, static ssize_t timeouts_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct tpm_chip *chip = dev_get_drvdata(dev); struct tpm_chip *chip = to_tpm_chip(dev);
return sprintf(buf, "%d %d %d %d [%s]\n", return sprintf(buf, "%d %d %d %d [%s]\n",
jiffies_to_usecs(chip->vendor.timeout_a), jiffies_to_usecs(chip->timeout_a),
jiffies_to_usecs(chip->vendor.timeout_b), jiffies_to_usecs(chip->timeout_b),
jiffies_to_usecs(chip->vendor.timeout_c), jiffies_to_usecs(chip->timeout_c),
jiffies_to_usecs(chip->vendor.timeout_d), jiffies_to_usecs(chip->timeout_d),
chip->vendor.timeout_adjusted chip->timeout_adjusted
? "adjusted" : "original"); ? "adjusted" : "original");
} }
static DEVICE_ATTR_RO(timeouts); static DEVICE_ATTR_RO(timeouts);
...@@ -281,19 +282,12 @@ static const struct attribute_group tpm_dev_group = { ...@@ -281,19 +282,12 @@ static const struct attribute_group tpm_dev_group = {
.attrs = tpm_dev_attrs, .attrs = tpm_dev_attrs,
}; };
int tpm_sysfs_add_device(struct tpm_chip *chip) void tpm_sysfs_add_device(struct tpm_chip *chip)
{ {
int err; /* The sysfs routines rely on an implicit tpm_try_get_ops, device_del
err = sysfs_create_group(&chip->pdev->kobj, * is called before ops is null'd and the sysfs core synchronizes this
&tpm_dev_group); * removal so that no callbacks are running or can run again
*/
if (err) WARN_ON(chip->groups_cnt != 0);
dev_err(chip->pdev, chip->groups[chip->groups_cnt++] = &tpm_dev_group;
"failed to create sysfs attributes, %d\n", err);
return err;
}
void tpm_sysfs_del_device(struct tpm_chip *chip)
{
sysfs_remove_group(&chip->pdev->kobj, &tpm_dev_group);
} }
...@@ -19,6 +19,10 @@ ...@@ -19,6 +19,10 @@
* License. * License.
* *
*/ */
#ifndef __TPM_H__
#define __TPM_H__
#include <linux/module.h> #include <linux/module.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/fs.h> #include <linux/fs.h>
...@@ -34,7 +38,7 @@ ...@@ -34,7 +38,7 @@
enum tpm_const { enum tpm_const {
TPM_MINOR = 224, /* officially assigned */ TPM_MINOR = 224, /* officially assigned */
TPM_BUFSIZE = 4096, TPM_BUFSIZE = 4096,
TPM_NUM_DEVICES = 256, TPM_NUM_DEVICES = 65536,
TPM_RETRY = 50, /* 5 seconds */ TPM_RETRY = 50, /* 5 seconds */
}; };
...@@ -128,33 +132,6 @@ enum tpm2_startup_types { ...@@ -128,33 +132,6 @@ enum tpm2_startup_types {
TPM2_SU_STATE = 0x0001, TPM2_SU_STATE = 0x0001,
}; };
struct tpm_chip;
struct tpm_vendor_specific {
void __iomem *iobase; /* ioremapped address */
unsigned long base; /* TPM base address */
int irq;
int region_size;
int have_region;
struct list_head list;
int locality;
unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */
bool timeout_adjusted;
unsigned long duration[3]; /* jiffies */
bool duration_adjusted;
void *priv;
wait_queue_head_t read_queue;
wait_queue_head_t int_queue;
u16 manufacturer_id;
};
#define TPM_VPRIV(c) ((c)->vendor.priv)
#define TPM_VID_INTEL 0x8086 #define TPM_VID_INTEL 0x8086
#define TPM_VID_WINBOND 0x1050 #define TPM_VID_WINBOND 0x1050
#define TPM_VID_STM 0x104A #define TPM_VID_STM 0x104A
...@@ -164,44 +141,48 @@ struct tpm_vendor_specific { ...@@ -164,44 +141,48 @@ struct tpm_vendor_specific {
enum tpm_chip_flags { enum tpm_chip_flags {
TPM_CHIP_FLAG_REGISTERED = BIT(0), TPM_CHIP_FLAG_REGISTERED = BIT(0),
TPM_CHIP_FLAG_TPM2 = BIT(1), TPM_CHIP_FLAG_TPM2 = BIT(1),
TPM_CHIP_FLAG_IRQ = BIT(2),
TPM_CHIP_FLAG_VIRTUAL = BIT(3),
}; };
struct tpm_chip { struct tpm_chip {
struct device *pdev; /* Device stuff */
struct device dev; struct device dev;
struct cdev cdev; struct cdev cdev;
/* A driver callback under ops cannot be run unless ops_sem is held
* (sometimes implicitly, eg for the sysfs code). ops becomes null
* when the driver is unregistered, see tpm_try_get_ops.
*/
struct rw_semaphore ops_sem;
const struct tpm_class_ops *ops; const struct tpm_class_ops *ops;
unsigned int flags; unsigned int flags;
int dev_num; /* /dev/tpm# */ int dev_num; /* /dev/tpm# */
char devname[7];
unsigned long is_open; /* only one allowed */ unsigned long is_open; /* only one allowed */
int time_expired;
struct mutex tpm_mutex; /* tpm is processing */ struct mutex tpm_mutex; /* tpm is processing */
struct tpm_vendor_specific vendor; unsigned long timeout_a; /* jiffies */
unsigned long timeout_b; /* jiffies */
unsigned long timeout_c; /* jiffies */
unsigned long timeout_d; /* jiffies */
bool timeout_adjusted;
unsigned long duration[3]; /* jiffies */
bool duration_adjusted;
struct dentry **bios_dir; struct dentry **bios_dir;
#ifdef CONFIG_ACPI const struct attribute_group *groups[3];
const struct attribute_group *groups[2];
unsigned int groups_cnt; unsigned int groups_cnt;
#ifdef CONFIG_ACPI
acpi_handle acpi_dev_handle; acpi_handle acpi_dev_handle;
char ppi_version[TPM_PPI_VERSION_LEN + 1]; char ppi_version[TPM_PPI_VERSION_LEN + 1];
#endif /* CONFIG_ACPI */ #endif /* CONFIG_ACPI */
struct list_head list;
}; };
#define to_tpm_chip(d) container_of(d, struct tpm_chip, dev) #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
static inline void tpm_chip_put(struct tpm_chip *chip)
{
module_put(chip->pdev->driver->owner);
}
static inline int tpm_read_index(int base, int index) static inline int tpm_read_index(int base, int index)
{ {
outb(index, base); outb(index, base);
...@@ -493,14 +474,17 @@ static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value) ...@@ -493,14 +474,17 @@ static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
extern struct class *tpm_class; extern struct class *tpm_class;
extern dev_t tpm_devt; extern dev_t tpm_devt;
extern const struct file_operations tpm_fops; extern const struct file_operations tpm_fops;
extern struct idr dev_nums_idr;
ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); ssize_t tpm_getcap(struct tpm_chip *chip, __be32 subcap_id, cap_t *cap,
const char *desc);
ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
size_t bufsiz); size_t bufsiz);
ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd, int len, ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd, int len,
const char *desc); const char *desc);
extern int tpm_get_timeouts(struct tpm_chip *); extern int tpm_get_timeouts(struct tpm_chip *);
extern void tpm_gen_interrupt(struct tpm_chip *); extern void tpm_gen_interrupt(struct tpm_chip *);
int tpm1_auto_startup(struct tpm_chip *chip);
extern int tpm_do_selftest(struct tpm_chip *); extern int tpm_do_selftest(struct tpm_chip *);
extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
extern int tpm_pm_suspend(struct device *); extern int tpm_pm_suspend(struct device *);
...@@ -509,13 +493,17 @@ extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long, ...@@ -509,13 +493,17 @@ extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
wait_queue_head_t *, bool); wait_queue_head_t *, bool);
struct tpm_chip *tpm_chip_find_get(int chip_num); struct tpm_chip *tpm_chip_find_get(int chip_num);
extern struct tpm_chip *tpmm_chip_alloc(struct device *dev, __must_check int tpm_try_get_ops(struct tpm_chip *chip);
void tpm_put_ops(struct tpm_chip *chip);
extern struct tpm_chip *tpm_chip_alloc(struct device *dev,
const struct tpm_class_ops *ops);
extern struct tpm_chip *tpmm_chip_alloc(struct device *pdev,
const struct tpm_class_ops *ops); const struct tpm_class_ops *ops);
extern int tpm_chip_register(struct tpm_chip *chip); extern int tpm_chip_register(struct tpm_chip *chip);
extern void tpm_chip_unregister(struct tpm_chip *chip); extern void tpm_chip_unregister(struct tpm_chip *chip);
int tpm_sysfs_add_device(struct tpm_chip *chip); void tpm_sysfs_add_device(struct tpm_chip *chip);
void tpm_sysfs_del_device(struct tpm_chip *chip);
int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
...@@ -539,9 +527,9 @@ int tpm2_unseal_trusted(struct tpm_chip *chip, ...@@ -539,9 +527,9 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
u32 *value, const char *desc); u32 *value, const char *desc);
extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type); int tpm2_auto_startup(struct tpm_chip *chip);
extern void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); extern void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32); extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32);
extern int tpm2_do_selftest(struct tpm_chip *chip);
extern int tpm2_gen_interrupt(struct tpm_chip *chip); extern int tpm2_gen_interrupt(struct tpm_chip *chip);
extern int tpm2_probe(struct tpm_chip *chip); extern int tpm2_probe(struct tpm_chip *chip);
#endif
...@@ -597,7 +597,7 @@ static void tpm2_flush_context(struct tpm_chip *chip, u32 handle) ...@@ -597,7 +597,7 @@ static void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT); rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
if (rc) { if (rc) {
dev_warn(chip->pdev, "0x%08x was not flushed, out of memory\n", dev_warn(&chip->dev, "0x%08x was not flushed, out of memory\n",
handle); handle);
return; return;
} }
...@@ -606,7 +606,7 @@ static void tpm2_flush_context(struct tpm_chip *chip, u32 handle) ...@@ -606,7 +606,7 @@ static void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "flushing context"); rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "flushing context");
if (rc) if (rc)
dev_warn(chip->pdev, "0x%08x was not flushed, rc=%d\n", handle, dev_warn(&chip->dev, "0x%08x was not flushed, rc=%d\n", handle,
rc); rc);
tpm_buf_destroy(&buf); tpm_buf_destroy(&buf);
...@@ -703,7 +703,7 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value, ...@@ -703,7 +703,7 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value,
rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), desc); rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), desc);
if (!rc) if (!rc)
*value = cmd.params.get_tpm_pt_out.value; *value = be32_to_cpu(cmd.params.get_tpm_pt_out.value);
return rc; return rc;
} }
...@@ -728,7 +728,7 @@ static const struct tpm_input_header tpm2_startup_header = { ...@@ -728,7 +728,7 @@ static const struct tpm_input_header tpm2_startup_header = {
* returned it remarks a POSIX error code. If a positive number is returned * returned it remarks a POSIX error code. If a positive number is returned
* it remarks a TPM error. * it remarks a TPM error.
*/ */
int tpm2_startup(struct tpm_chip *chip, u16 startup_type) static int tpm2_startup(struct tpm_chip *chip, u16 startup_type)
{ {
struct tpm2_cmd cmd; struct tpm2_cmd cmd;
...@@ -738,7 +738,6 @@ int tpm2_startup(struct tpm_chip *chip, u16 startup_type) ...@@ -738,7 +738,6 @@ int tpm2_startup(struct tpm_chip *chip, u16 startup_type)
return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), return tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
"attempting to start the TPM"); "attempting to start the TPM");
} }
EXPORT_SYMBOL_GPL(tpm2_startup);
#define TPM2_SHUTDOWN_IN_SIZE \ #define TPM2_SHUTDOWN_IN_SIZE \
(sizeof(struct tpm_input_header) + \ (sizeof(struct tpm_input_header) + \
...@@ -770,10 +769,9 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) ...@@ -770,10 +769,9 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
* except print the error code on a system failure. * except print the error code on a system failure.
*/ */
if (rc < 0) if (rc < 0)
dev_warn(chip->pdev, "transmit returned %d while stopping the TPM", dev_warn(&chip->dev, "transmit returned %d while stopping the TPM",
rc); rc);
} }
EXPORT_SYMBOL_GPL(tpm2_shutdown);
/* /*
* tpm2_calc_ordinal_duration() - maximum duration for a command * tpm2_calc_ordinal_duration() - maximum duration for a command
...@@ -793,7 +791,7 @@ unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) ...@@ -793,7 +791,7 @@ unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
index = tpm2_ordinal_duration[ordinal - TPM2_CC_FIRST]; index = tpm2_ordinal_duration[ordinal - TPM2_CC_FIRST];
if (index != TPM_UNDEFINED) if (index != TPM_UNDEFINED)
duration = chip->vendor.duration[index]; duration = chip->duration[index];
if (duration <= 0) if (duration <= 0)
duration = 2 * 60 * HZ; duration = 2 * 60 * HZ;
...@@ -837,7 +835,7 @@ static int tpm2_start_selftest(struct tpm_chip *chip, bool full) ...@@ -837,7 +835,7 @@ static int tpm2_start_selftest(struct tpm_chip *chip, bool full)
* immediately. This is a workaround for that. * immediately. This is a workaround for that.
*/ */
if (rc == TPM2_RC_TESTING) { if (rc == TPM2_RC_TESTING) {
dev_warn(chip->pdev, "Got RC_TESTING, ignoring\n"); dev_warn(&chip->dev, "Got RC_TESTING, ignoring\n");
rc = 0; rc = 0;
} }
...@@ -855,7 +853,7 @@ static int tpm2_start_selftest(struct tpm_chip *chip, bool full) ...@@ -855,7 +853,7 @@ static int tpm2_start_selftest(struct tpm_chip *chip, bool full)
* returned it remarks a POSIX error code. If a positive number is returned * returned it remarks a POSIX error code. If a positive number is returned
* it remarks a TPM error. * it remarks a TPM error.
*/ */
int tpm2_do_selftest(struct tpm_chip *chip) static int tpm2_do_selftest(struct tpm_chip *chip)
{ {
int rc; int rc;
unsigned int loops; unsigned int loops;
...@@ -895,7 +893,6 @@ int tpm2_do_selftest(struct tpm_chip *chip) ...@@ -895,7 +893,6 @@ int tpm2_do_selftest(struct tpm_chip *chip)
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(tpm2_do_selftest);
/** /**
* tpm2_gen_interrupt() - generate an interrupt * tpm2_gen_interrupt() - generate an interrupt
...@@ -943,3 +940,43 @@ int tpm2_probe(struct tpm_chip *chip) ...@@ -943,3 +940,43 @@ int tpm2_probe(struct tpm_chip *chip)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(tpm2_probe); EXPORT_SYMBOL_GPL(tpm2_probe);
/**
* tpm2_auto_startup - Perform the standard automatic TPM initialization
* sequence
* @chip: TPM chip to use
*
* Returns 0 on success, < 0 in case of fatal error.
*/
int tpm2_auto_startup(struct tpm_chip *chip)
{
int rc;
rc = tpm_get_timeouts(chip);
if (rc)
goto out;
rc = tpm2_do_selftest(chip);
if (rc != TPM2_RC_INITIALIZE) {
dev_err(&chip->dev, "TPM self test failed\n");
goto out;
}
if (rc == TPM2_RC_INITIALIZE) {
rc = tpm2_startup(chip, TPM2_SU_CLEAR);
if (rc)
goto out;
rc = tpm2_do_selftest(chip);
if (rc) {
dev_err(&chip->dev, "TPM self test failed\n");
goto out;
}
}
return rc;
out:
if (rc > 0)
rc = -ENODEV;
return rc;
}
...@@ -37,6 +37,7 @@ enum tpm_atmel_read_status { ...@@ -37,6 +37,7 @@ enum tpm_atmel_read_status {
static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{ {
struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev);
u8 status, *hdr = buf; u8 status, *hdr = buf;
u32 size; u32 size;
int i; int i;
...@@ -47,12 +48,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -47,12 +48,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
return -EIO; return -EIO;
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
status = ioread8(chip->vendor.iobase + 1); status = ioread8(priv->iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) { if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->pdev, "error reading header\n"); dev_err(&chip->dev, "error reading header\n");
return -EIO; return -EIO;
} }
*buf++ = ioread8(chip->vendor.iobase); *buf++ = ioread8(priv->iobase);
} }
/* size of the data received */ /* size of the data received */
...@@ -60,12 +61,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -60,12 +61,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
size = be32_to_cpu(*native_size); size = be32_to_cpu(*native_size);
if (count < size) { if (count < size) {
dev_err(chip->pdev, dev_err(&chip->dev,
"Recv size(%d) less than available space\n", size); "Recv size(%d) less than available space\n", size);
for (; i < size; i++) { /* clear the waiting data anyway */ for (; i < size; i++) { /* clear the waiting data anyway */
status = ioread8(chip->vendor.iobase + 1); status = ioread8(priv->iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) { if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->pdev, "error reading data\n"); dev_err(&chip->dev, "error reading data\n");
return -EIO; return -EIO;
} }
} }
...@@ -74,19 +75,19 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -74,19 +75,19 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
/* read all the data available */ /* read all the data available */
for (; i < size; i++) { for (; i < size; i++) {
status = ioread8(chip->vendor.iobase + 1); status = ioread8(priv->iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) { if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->pdev, "error reading data\n"); dev_err(&chip->dev, "error reading data\n");
return -EIO; return -EIO;
} }
*buf++ = ioread8(chip->vendor.iobase); *buf++ = ioread8(priv->iobase);
} }
/* make sure data available is gone */ /* make sure data available is gone */
status = ioread8(chip->vendor.iobase + 1); status = ioread8(priv->iobase + 1);
if (status & ATML_STATUS_DATA_AVAIL) { if (status & ATML_STATUS_DATA_AVAIL) {
dev_err(chip->pdev, "data available is stuck\n"); dev_err(&chip->dev, "data available is stuck\n");
return -EIO; return -EIO;
} }
...@@ -95,12 +96,13 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -95,12 +96,13 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count)
{ {
struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev);
int i; int i;
dev_dbg(chip->pdev, "tpm_atml_send:\n"); dev_dbg(&chip->dev, "tpm_atml_send:\n");
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
dev_dbg(chip->pdev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); dev_dbg(&chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]);
iowrite8(buf[i], chip->vendor.iobase); iowrite8(buf[i], priv->iobase);
} }
return count; return count;
...@@ -108,12 +110,16 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -108,12 +110,16 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count)
static void tpm_atml_cancel(struct tpm_chip *chip) static void tpm_atml_cancel(struct tpm_chip *chip)
{ {
iowrite8(ATML_STATUS_ABORT, chip->vendor.iobase + 1); struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev);
iowrite8(ATML_STATUS_ABORT, priv->iobase + 1);
} }
static u8 tpm_atml_status(struct tpm_chip *chip) static u8 tpm_atml_status(struct tpm_chip *chip)
{ {
return ioread8(chip->vendor.iobase + 1); struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev);
return ioread8(priv->iobase + 1);
} }
static bool tpm_atml_req_canceled(struct tpm_chip *chip, u8 status) static bool tpm_atml_req_canceled(struct tpm_chip *chip, u8 status)
...@@ -136,13 +142,13 @@ static struct platform_device *pdev; ...@@ -136,13 +142,13 @@ static struct platform_device *pdev;
static void atml_plat_remove(void) static void atml_plat_remove(void)
{ {
struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev);
if (chip) { if (chip) {
tpm_chip_unregister(chip); tpm_chip_unregister(chip);
if (chip->vendor.have_region) if (priv->have_region)
atmel_release_region(chip->vendor.base, atmel_release_region(priv->base, priv->region_size);
chip->vendor.region_size); atmel_put_base_addr(priv->iobase);
atmel_put_base_addr(chip->vendor.iobase);
platform_device_unregister(pdev); platform_device_unregister(pdev);
} }
} }
...@@ -163,6 +169,7 @@ static int __init init_atmel(void) ...@@ -163,6 +169,7 @@ static int __init init_atmel(void)
int have_region, region_size; int have_region, region_size;
unsigned long base; unsigned long base;
struct tpm_chip *chip; struct tpm_chip *chip;
struct tpm_atmel_priv *priv;
rc = platform_driver_register(&atml_drv); rc = platform_driver_register(&atml_drv);
if (rc) if (rc)
...@@ -183,16 +190,24 @@ static int __init init_atmel(void) ...@@ -183,16 +190,24 @@ static int __init init_atmel(void)
goto err_rel_reg; goto err_rel_reg;
} }
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) {
rc = -ENOMEM;
goto err_unreg_dev;
}
priv->iobase = iobase;
priv->base = base;
priv->have_region = have_region;
priv->region_size = region_size;
chip = tpmm_chip_alloc(&pdev->dev, &tpm_atmel); chip = tpmm_chip_alloc(&pdev->dev, &tpm_atmel);
if (IS_ERR(chip)) { if (IS_ERR(chip)) {
rc = PTR_ERR(chip); rc = PTR_ERR(chip);
goto err_unreg_dev; goto err_unreg_dev;
} }
chip->vendor.iobase = iobase; dev_set_drvdata(&chip->dev, priv);
chip->vendor.base = base;
chip->vendor.have_region = have_region;
chip->vendor.region_size = region_size;
rc = tpm_chip_register(chip); rc = tpm_chip_register(chip);
if (rc) if (rc)
......
...@@ -22,12 +22,19 @@ ...@@ -22,12 +22,19 @@
* *
*/ */
struct tpm_atmel_priv {
int region_size;
int have_region;
unsigned long base;
void __iomem *iobase;
};
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
#include <asm/prom.h> #include <asm/prom.h>
#define atmel_getb(chip, offset) readb(chip->vendor->iobase + offset); #define atmel_getb(priv, offset) readb(priv->iobase + offset)
#define atmel_putb(val, chip, offset) writeb(val, chip->vendor->iobase + offset) #define atmel_putb(val, priv, offset) writeb(val, priv->iobase + offset)
#define atmel_request_region request_mem_region #define atmel_request_region request_mem_region
#define atmel_release_region release_mem_region #define atmel_release_region release_mem_region
...@@ -78,8 +85,9 @@ static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) ...@@ -78,8 +85,9 @@ static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
return ioremap(*base, *region_size); return ioremap(*base, *region_size);
} }
#else #else
#define atmel_getb(chip, offset) inb(chip->vendor->base + offset) #define atmel_getb(chip, offset) inb(atmel_get_priv(chip)->base + offset)
#define atmel_putb(val, chip, offset) outb(val, chip->vendor->base + offset) #define atmel_putb(val, chip, offset) \
outb(val, atmel_get_priv(chip)->base + offset)
#define atmel_request_region request_region #define atmel_request_region request_region
#define atmel_release_region release_region #define atmel_release_region release_region
/* Atmel definitions */ /* Atmel definitions */
......
...@@ -77,7 +77,6 @@ enum crb_flags { ...@@ -77,7 +77,6 @@ enum crb_flags {
struct crb_priv { struct crb_priv {
unsigned int flags; unsigned int flags;
struct resource res;
void __iomem *iobase; void __iomem *iobase;
struct crb_control_area __iomem *cca; struct crb_control_area __iomem *cca;
u8 __iomem *cmd; u8 __iomem *cmd;
...@@ -88,7 +87,7 @@ static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, tpm_pm_resume); ...@@ -88,7 +87,7 @@ static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, tpm_pm_resume);
static u8 crb_status(struct tpm_chip *chip) static u8 crb_status(struct tpm_chip *chip)
{ {
struct crb_priv *priv = chip->vendor.priv; struct crb_priv *priv = dev_get_drvdata(&chip->dev);
u8 sts = 0; u8 sts = 0;
if ((ioread32(&priv->cca->start) & CRB_START_INVOKE) != if ((ioread32(&priv->cca->start) & CRB_START_INVOKE) !=
...@@ -100,7 +99,7 @@ static u8 crb_status(struct tpm_chip *chip) ...@@ -100,7 +99,7 @@ static u8 crb_status(struct tpm_chip *chip)
static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count) static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{ {
struct crb_priv *priv = chip->vendor.priv; struct crb_priv *priv = dev_get_drvdata(&chip->dev);
unsigned int expected; unsigned int expected;
/* sanity check */ /* sanity check */
...@@ -140,7 +139,7 @@ static int crb_do_acpi_start(struct tpm_chip *chip) ...@@ -140,7 +139,7 @@ static int crb_do_acpi_start(struct tpm_chip *chip)
static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len) static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
{ {
struct crb_priv *priv = chip->vendor.priv; struct crb_priv *priv = dev_get_drvdata(&chip->dev);
int rc = 0; int rc = 0;
if (len > ioread32(&priv->cca->cmd_size)) { if (len > ioread32(&priv->cca->cmd_size)) {
...@@ -167,7 +166,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -167,7 +166,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
static void crb_cancel(struct tpm_chip *chip) static void crb_cancel(struct tpm_chip *chip)
{ {
struct crb_priv *priv = chip->vendor.priv; struct crb_priv *priv = dev_get_drvdata(&chip->dev);
iowrite32(cpu_to_le32(CRB_CANCEL_INVOKE), &priv->cca->cancel); iowrite32(cpu_to_le32(CRB_CANCEL_INVOKE), &priv->cca->cancel);
...@@ -182,13 +181,14 @@ static void crb_cancel(struct tpm_chip *chip) ...@@ -182,13 +181,14 @@ static void crb_cancel(struct tpm_chip *chip)
static bool crb_req_canceled(struct tpm_chip *chip, u8 status) static bool crb_req_canceled(struct tpm_chip *chip, u8 status)
{ {
struct crb_priv *priv = chip->vendor.priv; struct crb_priv *priv = dev_get_drvdata(&chip->dev);
u32 cancel = ioread32(&priv->cca->cancel); u32 cancel = ioread32(&priv->cca->cancel);
return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE; return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE;
} }
static const struct tpm_class_ops tpm_crb = { static const struct tpm_class_ops tpm_crb = {
.flags = TPM_OPS_AUTO_STARTUP,
.status = crb_status, .status = crb_status,
.recv = crb_recv, .recv = crb_recv,
.send = crb_send, .send = crb_send,
...@@ -201,42 +201,33 @@ static const struct tpm_class_ops tpm_crb = { ...@@ -201,42 +201,33 @@ static const struct tpm_class_ops tpm_crb = {
static int crb_init(struct acpi_device *device, struct crb_priv *priv) static int crb_init(struct acpi_device *device, struct crb_priv *priv)
{ {
struct tpm_chip *chip; struct tpm_chip *chip;
int rc;
chip = tpmm_chip_alloc(&device->dev, &tpm_crb); chip = tpmm_chip_alloc(&device->dev, &tpm_crb);
if (IS_ERR(chip)) if (IS_ERR(chip))
return PTR_ERR(chip); return PTR_ERR(chip);
chip->vendor.priv = priv; dev_set_drvdata(&chip->dev, priv);
chip->acpi_dev_handle = device->handle; chip->acpi_dev_handle = device->handle;
chip->flags = TPM_CHIP_FLAG_TPM2; chip->flags = TPM_CHIP_FLAG_TPM2;
rc = tpm_get_timeouts(chip);
if (rc)
return rc;
rc = tpm2_do_selftest(chip);
if (rc)
return rc;
return tpm_chip_register(chip); return tpm_chip_register(chip);
} }
static int crb_check_resource(struct acpi_resource *ares, void *data) static int crb_check_resource(struct acpi_resource *ares, void *data)
{ {
struct crb_priv *priv = data; struct resource *io_res = data;
struct resource res; struct resource res;
if (acpi_dev_resource_memory(ares, &res)) { if (acpi_dev_resource_memory(ares, &res)) {
priv->res = res; *io_res = res;
priv->res.name = NULL; io_res->name = NULL;
} }
return 1; return 1;
} }
static void __iomem *crb_map_res(struct device *dev, struct crb_priv *priv, static void __iomem *crb_map_res(struct device *dev, struct crb_priv *priv,
u64 start, u32 size) struct resource *io_res, u64 start, u32 size)
{ {
struct resource new_res = { struct resource new_res = {
.start = start, .start = start,
...@@ -246,53 +237,74 @@ static void __iomem *crb_map_res(struct device *dev, struct crb_priv *priv, ...@@ -246,53 +237,74 @@ static void __iomem *crb_map_res(struct device *dev, struct crb_priv *priv,
/* Detect a 64 bit address on a 32 bit system */ /* Detect a 64 bit address on a 32 bit system */
if (start != new_res.start) if (start != new_res.start)
return ERR_PTR(-EINVAL); return (void __iomem *) ERR_PTR(-EINVAL);
if (!resource_contains(&priv->res, &new_res)) if (!resource_contains(io_res, &new_res))
return devm_ioremap_resource(dev, &new_res); return devm_ioremap_resource(dev, &new_res);
return priv->iobase + (new_res.start - priv->res.start); return priv->iobase + (new_res.start - io_res->start);
} }
static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
struct acpi_table_tpm2 *buf) struct acpi_table_tpm2 *buf)
{ {
struct list_head resources; struct list_head resources;
struct resource io_res;
struct device *dev = &device->dev; struct device *dev = &device->dev;
u64 pa; u64 cmd_pa;
u32 cmd_size;
u64 rsp_pa;
u32 rsp_size;
int ret; int ret;
INIT_LIST_HEAD(&resources); INIT_LIST_HEAD(&resources);
ret = acpi_dev_get_resources(device, &resources, crb_check_resource, ret = acpi_dev_get_resources(device, &resources, crb_check_resource,
priv); &io_res);
if (ret < 0) if (ret < 0)
return ret; return ret;
acpi_dev_free_resource_list(&resources); acpi_dev_free_resource_list(&resources);
if (resource_type(&priv->res) != IORESOURCE_MEM) { if (resource_type(&io_res) != IORESOURCE_MEM) {
dev_err(dev, dev_err(dev,
FW_BUG "TPM2 ACPI table does not define a memory resource\n"); FW_BUG "TPM2 ACPI table does not define a memory resource\n");
return -EINVAL; return -EINVAL;
} }
priv->iobase = devm_ioremap_resource(dev, &priv->res); priv->iobase = devm_ioremap_resource(dev, &io_res);
if (IS_ERR(priv->iobase)) if (IS_ERR(priv->iobase))
return PTR_ERR(priv->iobase); return PTR_ERR(priv->iobase);
priv->cca = crb_map_res(dev, priv, buf->control_address, 0x1000); priv->cca = crb_map_res(dev, priv, &io_res, buf->control_address,
sizeof(struct crb_control_area));
if (IS_ERR(priv->cca)) if (IS_ERR(priv->cca))
return PTR_ERR(priv->cca); return PTR_ERR(priv->cca);
pa = ((u64) ioread32(&priv->cca->cmd_pa_high) << 32) | cmd_pa = ((u64) ioread32(&priv->cca->cmd_pa_high) << 32) |
(u64) ioread32(&priv->cca->cmd_pa_low); (u64) ioread32(&priv->cca->cmd_pa_low);
priv->cmd = crb_map_res(dev, priv, pa, ioread32(&priv->cca->cmd_size)); cmd_size = ioread32(&priv->cca->cmd_size);
priv->cmd = crb_map_res(dev, priv, &io_res, cmd_pa, cmd_size);
if (IS_ERR(priv->cmd)) if (IS_ERR(priv->cmd))
return PTR_ERR(priv->cmd); return PTR_ERR(priv->cmd);
memcpy_fromio(&pa, &priv->cca->rsp_pa, 8); memcpy_fromio(&rsp_pa, &priv->cca->rsp_pa, 8);
pa = le64_to_cpu(pa); rsp_pa = le64_to_cpu(rsp_pa);
priv->rsp = crb_map_res(dev, priv, pa, ioread32(&priv->cca->rsp_size)); rsp_size = ioread32(&priv->cca->rsp_size);
return PTR_ERR_OR_ZERO(priv->rsp);
if (cmd_pa != rsp_pa) {
priv->rsp = crb_map_res(dev, priv, &io_res, rsp_pa, rsp_size);
return PTR_ERR_OR_ZERO(priv->rsp);
}
/* According to the PTP specification, overlapping command and response
* buffer sizes must be identical.
*/
if (cmd_size != rsp_size) {
dev_err(dev, FW_BUG "overlapping command and response buffer sizes are not identical");
return -EINVAL;
}
priv->rsp = priv->cmd;
return 0;
} }
static int crb_acpi_add(struct acpi_device *device) static int crb_acpi_add(struct acpi_device *device)
...@@ -344,9 +356,6 @@ static int crb_acpi_remove(struct acpi_device *device) ...@@ -344,9 +356,6 @@ static int crb_acpi_remove(struct acpi_device *device)
struct device *dev = &device->dev; struct device *dev = &device->dev;
struct tpm_chip *chip = dev_get_drvdata(dev); struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip->flags & TPM_CHIP_FLAG_TPM2)
tpm2_shutdown(chip, TPM2_SU_CLEAR);
tpm_chip_unregister(chip); tpm_chip_unregister(chip);
return 0; return 0;
......
...@@ -403,7 +403,7 @@ static int is_bad(void *p) ...@@ -403,7 +403,7 @@ static int is_bad(void *p)
return 0; return 0;
} }
struct dentry **tpm_bios_log_setup(char *name) struct dentry **tpm_bios_log_setup(const char *name)
{ {
struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file; struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
......
...@@ -77,10 +77,10 @@ int read_log(struct tpm_bios_log *log); ...@@ -77,10 +77,10 @@ int read_log(struct tpm_bios_log *log);
#if defined(CONFIG_TCG_IBMVTPM) || defined(CONFIG_TCG_IBMVTPM_MODULE) || \ #if defined(CONFIG_TCG_IBMVTPM) || defined(CONFIG_TCG_IBMVTPM_MODULE) || \
defined(CONFIG_ACPI) defined(CONFIG_ACPI)
extern struct dentry **tpm_bios_log_setup(char *); extern struct dentry **tpm_bios_log_setup(const char *);
extern void tpm_bios_log_teardown(struct dentry **); extern void tpm_bios_log_teardown(struct dentry **);
#else #else
static inline struct dentry **tpm_bios_log_setup(char *name) static inline struct dentry **tpm_bios_log_setup(const char *name)
{ {
return NULL; return NULL;
} }
......
...@@ -51,8 +51,8 @@ struct priv_data { ...@@ -51,8 +51,8 @@ struct priv_data {
static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len) static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len)
{ {
struct priv_data *priv = chip->vendor.priv; struct priv_data *priv = dev_get_drvdata(&chip->dev);
struct i2c_client *client = to_i2c_client(chip->pdev); struct i2c_client *client = to_i2c_client(chip->dev.parent);
s32 status; s32 status;
priv->len = 0; priv->len = 0;
...@@ -62,7 +62,7 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -62,7 +62,7 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len)
status = i2c_master_send(client, buf, len); status = i2c_master_send(client, buf, len);
dev_dbg(chip->pdev, dev_dbg(&chip->dev,
"%s(buf=%*ph len=%0zx) -> sts=%d\n", __func__, "%s(buf=%*ph len=%0zx) -> sts=%d\n", __func__,
(int)min_t(size_t, 64, len), buf, len, status); (int)min_t(size_t, 64, len), buf, len, status);
return status; return status;
...@@ -70,8 +70,8 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -70,8 +70,8 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len)
static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{ {
struct priv_data *priv = chip->vendor.priv; struct priv_data *priv = dev_get_drvdata(&chip->dev);
struct i2c_client *client = to_i2c_client(chip->pdev); struct i2c_client *client = to_i2c_client(chip->dev.parent);
struct tpm_output_header *hdr = struct tpm_output_header *hdr =
(struct tpm_output_header *)priv->buffer; (struct tpm_output_header *)priv->buffer;
u32 expected_len; u32 expected_len;
...@@ -88,7 +88,7 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -88,7 +88,7 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
return -ENOMEM; return -ENOMEM;
if (priv->len >= expected_len) { if (priv->len >= expected_len) {
dev_dbg(chip->pdev, dev_dbg(&chip->dev,
"%s early(buf=%*ph count=%0zx) -> ret=%d\n", __func__, "%s early(buf=%*ph count=%0zx) -> ret=%d\n", __func__,
(int)min_t(size_t, 64, expected_len), buf, count, (int)min_t(size_t, 64, expected_len), buf, count,
expected_len); expected_len);
...@@ -97,7 +97,7 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -97,7 +97,7 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
} }
rc = i2c_master_recv(client, buf, expected_len); rc = i2c_master_recv(client, buf, expected_len);
dev_dbg(chip->pdev, dev_dbg(&chip->dev,
"%s reread(buf=%*ph count=%0zx) -> ret=%d\n", __func__, "%s reread(buf=%*ph count=%0zx) -> ret=%d\n", __func__,
(int)min_t(size_t, 64, expected_len), buf, count, (int)min_t(size_t, 64, expected_len), buf, count,
expected_len); expected_len);
...@@ -106,13 +106,13 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -106,13 +106,13 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
static void i2c_atmel_cancel(struct tpm_chip *chip) static void i2c_atmel_cancel(struct tpm_chip *chip)
{ {
dev_err(chip->pdev, "TPM operation cancellation was requested, but is not supported"); dev_err(&chip->dev, "TPM operation cancellation was requested, but is not supported");
} }
static u8 i2c_atmel_read_status(struct tpm_chip *chip) static u8 i2c_atmel_read_status(struct tpm_chip *chip)
{ {
struct priv_data *priv = chip->vendor.priv; struct priv_data *priv = dev_get_drvdata(&chip->dev);
struct i2c_client *client = to_i2c_client(chip->pdev); struct i2c_client *client = to_i2c_client(chip->dev.parent);
int rc; int rc;
/* The TPM fails the I2C read until it is ready, so we do the entire /* The TPM fails the I2C read until it is ready, so we do the entire
...@@ -125,7 +125,7 @@ static u8 i2c_atmel_read_status(struct tpm_chip *chip) ...@@ -125,7 +125,7 @@ static u8 i2c_atmel_read_status(struct tpm_chip *chip)
/* Once the TPM has completed the command the command remains readable /* Once the TPM has completed the command the command remains readable
* until another command is issued. */ * until another command is issued. */
rc = i2c_master_recv(client, priv->buffer, sizeof(priv->buffer)); rc = i2c_master_recv(client, priv->buffer, sizeof(priv->buffer));
dev_dbg(chip->pdev, dev_dbg(&chip->dev,
"%s: sts=%d", __func__, rc); "%s: sts=%d", __func__, rc);
if (rc <= 0) if (rc <= 0)
return 0; return 0;
...@@ -141,6 +141,7 @@ static bool i2c_atmel_req_canceled(struct tpm_chip *chip, u8 status) ...@@ -141,6 +141,7 @@ static bool i2c_atmel_req_canceled(struct tpm_chip *chip, u8 status)
} }
static const struct tpm_class_ops i2c_atmel = { static const struct tpm_class_ops i2c_atmel = {
.flags = TPM_OPS_AUTO_STARTUP,
.status = i2c_atmel_read_status, .status = i2c_atmel_read_status,
.recv = i2c_atmel_recv, .recv = i2c_atmel_recv,
.send = i2c_atmel_send, .send = i2c_atmel_send,
...@@ -155,6 +156,7 @@ static int i2c_atmel_probe(struct i2c_client *client, ...@@ -155,6 +156,7 @@ static int i2c_atmel_probe(struct i2c_client *client,
{ {
struct tpm_chip *chip; struct tpm_chip *chip;
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct priv_data *priv;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV; return -ENODEV;
...@@ -163,26 +165,21 @@ static int i2c_atmel_probe(struct i2c_client *client, ...@@ -163,26 +165,21 @@ static int i2c_atmel_probe(struct i2c_client *client,
if (IS_ERR(chip)) if (IS_ERR(chip))
return PTR_ERR(chip); return PTR_ERR(chip);
chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data), priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL);
GFP_KERNEL); if (!priv)
if (!chip->vendor.priv)
return -ENOMEM; return -ENOMEM;
/* Default timeouts */ /* Default timeouts */
chip->vendor.timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); chip->timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
chip->vendor.timeout_b = msecs_to_jiffies(TPM_I2C_LONG_TIMEOUT); chip->timeout_b = msecs_to_jiffies(TPM_I2C_LONG_TIMEOUT);
chip->vendor.timeout_c = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); chip->timeout_c = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
chip->vendor.timeout_d = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); chip->timeout_d = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
chip->vendor.irq = 0;
dev_set_drvdata(&chip->dev, priv);
/* There is no known way to probe for this device, and all version /* There is no known way to probe for this device, and all version
* information seems to be read via TPM commands. Thus we rely on the * information seems to be read via TPM commands. Thus we rely on the
* TPM startup process in the common code to detect the device. */ * TPM startup process in the common code to detect the device. */
if (tpm_get_timeouts(chip))
return -ENODEV;
if (tpm_do_selftest(chip))
return -ENODEV;
return tpm_chip_register(chip); return tpm_chip_register(chip);
} }
......
...@@ -66,6 +66,7 @@ enum i2c_chip_type { ...@@ -66,6 +66,7 @@ enum i2c_chip_type {
/* Structure to store I2C TPM specific stuff */ /* Structure to store I2C TPM specific stuff */
struct tpm_inf_dev { struct tpm_inf_dev {
struct i2c_client *client; struct i2c_client *client;
int locality;
u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */ u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */
struct tpm_chip *chip; struct tpm_chip *chip;
enum i2c_chip_type chip_type; enum i2c_chip_type chip_type;
...@@ -288,7 +289,7 @@ static int check_locality(struct tpm_chip *chip, int loc) ...@@ -288,7 +289,7 @@ static int check_locality(struct tpm_chip *chip, int loc)
if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) {
chip->vendor.locality = loc; tpm_dev.locality = loc;
return loc; return loc;
} }
...@@ -320,7 +321,7 @@ static int request_locality(struct tpm_chip *chip, int loc) ...@@ -320,7 +321,7 @@ static int request_locality(struct tpm_chip *chip, int loc)
iic_tpm_write(TPM_ACCESS(loc), &buf, 1); iic_tpm_write(TPM_ACCESS(loc), &buf, 1);
/* wait for burstcount */ /* wait for burstcount */
stop = jiffies + chip->vendor.timeout_a; stop = jiffies + chip->timeout_a;
do { do {
if (check_locality(chip, loc) >= 0) if (check_locality(chip, loc) >= 0)
return loc; return loc;
...@@ -337,7 +338,7 @@ static u8 tpm_tis_i2c_status(struct tpm_chip *chip) ...@@ -337,7 +338,7 @@ static u8 tpm_tis_i2c_status(struct tpm_chip *chip)
u8 i = 0; u8 i = 0;
do { do {
if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0) if (iic_tpm_read(TPM_STS(tpm_dev.locality), &buf, 1) < 0)
return 0; return 0;
i++; i++;
...@@ -351,7 +352,7 @@ static void tpm_tis_i2c_ready(struct tpm_chip *chip) ...@@ -351,7 +352,7 @@ static void tpm_tis_i2c_ready(struct tpm_chip *chip)
{ {
/* this causes the current command to be aborted */ /* this causes the current command to be aborted */
u8 buf = TPM_STS_COMMAND_READY; u8 buf = TPM_STS_COMMAND_READY;
iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1); iic_tpm_write_long(TPM_STS(tpm_dev.locality), &buf, 1);
} }
static ssize_t get_burstcount(struct tpm_chip *chip) static ssize_t get_burstcount(struct tpm_chip *chip)
...@@ -362,10 +363,10 @@ static ssize_t get_burstcount(struct tpm_chip *chip) ...@@ -362,10 +363,10 @@ static ssize_t get_burstcount(struct tpm_chip *chip)
/* wait for burstcount */ /* wait for burstcount */
/* which timeout value, spec has 2 answers (c & d) */ /* which timeout value, spec has 2 answers (c & d) */
stop = jiffies + chip->vendor.timeout_d; stop = jiffies + chip->timeout_d;
do { do {
/* Note: STS is little endian */ /* Note: STS is little endian */
if (iic_tpm_read(TPM_STS(chip->vendor.locality)+1, buf, 3) < 0) if (iic_tpm_read(TPM_STS(tpm_dev.locality)+1, buf, 3) < 0)
burstcnt = 0; burstcnt = 0;
else else
burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0]; burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0];
...@@ -419,7 +420,7 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -419,7 +420,7 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
if (burstcnt > (count - size)) if (burstcnt > (count - size))
burstcnt = count - size; burstcnt = count - size;
rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality), rc = iic_tpm_read(TPM_DATA_FIFO(tpm_dev.locality),
&(buf[size]), burstcnt); &(buf[size]), burstcnt);
if (rc == 0) if (rc == 0)
size += burstcnt; size += burstcnt;
...@@ -446,7 +447,7 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -446,7 +447,7 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
/* read first 10 bytes, including tag, paramsize, and result */ /* read first 10 bytes, including tag, paramsize, and result */
size = recv_data(chip, buf, TPM_HEADER_SIZE); size = recv_data(chip, buf, TPM_HEADER_SIZE);
if (size < TPM_HEADER_SIZE) { if (size < TPM_HEADER_SIZE) {
dev_err(chip->pdev, "Unable to read header\n"); dev_err(&chip->dev, "Unable to read header\n");
goto out; goto out;
} }
...@@ -459,14 +460,14 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -459,14 +460,14 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
size += recv_data(chip, &buf[TPM_HEADER_SIZE], size += recv_data(chip, &buf[TPM_HEADER_SIZE],
expected - TPM_HEADER_SIZE); expected - TPM_HEADER_SIZE);
if (size < expected) { if (size < expected) {
dev_err(chip->pdev, "Unable to read remainder of result\n"); dev_err(&chip->dev, "Unable to read remainder of result\n");
size = -ETIME; size = -ETIME;
goto out; goto out;
} }
wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); wait_for_stat(chip, TPM_STS_VALID, chip->timeout_c, &status);
if (status & TPM_STS_DATA_AVAIL) { /* retry? */ if (status & TPM_STS_DATA_AVAIL) { /* retry? */
dev_err(chip->pdev, "Error left over data\n"); dev_err(&chip->dev, "Error left over data\n");
size = -EIO; size = -EIO;
goto out; goto out;
} }
...@@ -477,7 +478,7 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -477,7 +478,7 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
* so we sleep rather than keeping the bus busy * so we sleep rather than keeping the bus busy
*/ */
usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI); usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI);
release_locality(chip, chip->vendor.locality, 0); release_locality(chip, tpm_dev.locality, 0);
return size; return size;
} }
...@@ -500,7 +501,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -500,7 +501,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
tpm_tis_i2c_ready(chip); tpm_tis_i2c_ready(chip);
if (wait_for_stat if (wait_for_stat
(chip, TPM_STS_COMMAND_READY, (chip, TPM_STS_COMMAND_READY,
chip->vendor.timeout_b, &status) < 0) { chip->timeout_b, &status) < 0) {
rc = -ETIME; rc = -ETIME;
goto out_err; goto out_err;
} }
...@@ -516,7 +517,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -516,7 +517,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
if (burstcnt > (len - 1 - count)) if (burstcnt > (len - 1 - count))
burstcnt = len - 1 - count; burstcnt = len - 1 - count;
rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), rc = iic_tpm_write(TPM_DATA_FIFO(tpm_dev.locality),
&(buf[count]), burstcnt); &(buf[count]), burstcnt);
if (rc == 0) if (rc == 0)
count += burstcnt; count += burstcnt;
...@@ -530,7 +531,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -530,7 +531,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
} }
wait_for_stat(chip, TPM_STS_VALID, wait_for_stat(chip, TPM_STS_VALID,
chip->vendor.timeout_c, &status); chip->timeout_c, &status);
if ((status & TPM_STS_DATA_EXPECT) == 0) { if ((status & TPM_STS_DATA_EXPECT) == 0) {
rc = -EIO; rc = -EIO;
...@@ -539,15 +540,15 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -539,15 +540,15 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
} }
/* write last byte */ /* write last byte */
iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1); iic_tpm_write(TPM_DATA_FIFO(tpm_dev.locality), &(buf[count]), 1);
wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); wait_for_stat(chip, TPM_STS_VALID, chip->timeout_c, &status);
if ((status & TPM_STS_DATA_EXPECT) != 0) { if ((status & TPM_STS_DATA_EXPECT) != 0) {
rc = -EIO; rc = -EIO;
goto out_err; goto out_err;
} }
/* go and do it */ /* go and do it */
iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1); iic_tpm_write(TPM_STS(tpm_dev.locality), &sts, 1);
return len; return len;
out_err: out_err:
...@@ -556,7 +557,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -556,7 +557,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
* so we sleep rather than keeping the bus busy * so we sleep rather than keeping the bus busy
*/ */
usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI); usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI);
release_locality(chip, chip->vendor.locality, 0); release_locality(chip, tpm_dev.locality, 0);
return rc; return rc;
} }
...@@ -566,6 +567,7 @@ static bool tpm_tis_i2c_req_canceled(struct tpm_chip *chip, u8 status) ...@@ -566,6 +567,7 @@ static bool tpm_tis_i2c_req_canceled(struct tpm_chip *chip, u8 status)
} }
static const struct tpm_class_ops tpm_tis_i2c = { static const struct tpm_class_ops tpm_tis_i2c = {
.flags = TPM_OPS_AUTO_STARTUP,
.status = tpm_tis_i2c_status, .status = tpm_tis_i2c_status,
.recv = tpm_tis_i2c_recv, .recv = tpm_tis_i2c_recv,
.send = tpm_tis_i2c_send, .send = tpm_tis_i2c_send,
...@@ -585,14 +587,11 @@ static int tpm_tis_i2c_init(struct device *dev) ...@@ -585,14 +587,11 @@ static int tpm_tis_i2c_init(struct device *dev)
if (IS_ERR(chip)) if (IS_ERR(chip))
return PTR_ERR(chip); return PTR_ERR(chip);
/* Disable interrupts */
chip->vendor.irq = 0;
/* Default timeouts */ /* Default timeouts */
chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); chip->timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); chip->timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); chip->timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); chip->timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
if (request_locality(chip, 0) != 0) { if (request_locality(chip, 0) != 0) {
dev_err(dev, "could not request locality\n"); dev_err(dev, "could not request locality\n");
...@@ -619,15 +618,11 @@ static int tpm_tis_i2c_init(struct device *dev) ...@@ -619,15 +618,11 @@ static int tpm_tis_i2c_init(struct device *dev)
dev_info(dev, "1.2 TPM (device-id 0x%X)\n", vendor >> 16); dev_info(dev, "1.2 TPM (device-id 0x%X)\n", vendor >> 16);
INIT_LIST_HEAD(&chip->vendor.list);
tpm_dev.chip = chip; tpm_dev.chip = chip;
tpm_get_timeouts(chip);
tpm_do_selftest(chip);
return tpm_chip_register(chip); return tpm_chip_register(chip);
out_release: out_release:
release_locality(chip, chip->vendor.locality, 1); release_locality(chip, tpm_dev.locality, 1);
tpm_dev.client = NULL; tpm_dev.client = NULL;
out_err: out_err:
return rc; return rc;
...@@ -699,7 +694,7 @@ static int tpm_tis_i2c_remove(struct i2c_client *client) ...@@ -699,7 +694,7 @@ static int tpm_tis_i2c_remove(struct i2c_client *client)
struct tpm_chip *chip = tpm_dev.chip; struct tpm_chip *chip = tpm_dev.chip;
tpm_chip_unregister(chip); tpm_chip_unregister(chip);
release_locality(chip, chip->vendor.locality, 1); release_locality(chip, tpm_dev.locality, 1);
tpm_dev.client = NULL; tpm_dev.client = NULL;
return 0; return 0;
......
/****************************************************************************** /******************************************************************************
* Nuvoton TPM I2C Device Driver Interface for WPCT301/NPCT501, * Nuvoton TPM I2C Device Driver Interface for WPCT301/NPCT501/NPCT6XX,
* based on the TCG TPM Interface Spec version 1.2. * based on the TCG TPM Interface Spec version 1.2.
* Specifications at www.trustedcomputinggroup.org * Specifications at www.trustedcomputinggroup.org
* *
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/of_device.h>
#include "tpm.h" #include "tpm.h"
/* I2C interface offsets */ /* I2C interface offsets */
...@@ -52,10 +53,13 @@ ...@@ -52,10 +53,13 @@
#define TPM_I2C_RETRY_DELAY_SHORT 2 /* msec */ #define TPM_I2C_RETRY_DELAY_SHORT 2 /* msec */
#define TPM_I2C_RETRY_DELAY_LONG 10 /* msec */ #define TPM_I2C_RETRY_DELAY_LONG 10 /* msec */
#define I2C_DRIVER_NAME "tpm_i2c_nuvoton" #define OF_IS_TPM2 ((void *)1)
#define I2C_IS_TPM2 1
struct priv_data { struct priv_data {
int irq;
unsigned int intrs; unsigned int intrs;
wait_queue_head_t read_queue;
}; };
static s32 i2c_nuvoton_read_buf(struct i2c_client *client, u8 offset, u8 size, static s32 i2c_nuvoton_read_buf(struct i2c_client *client, u8 offset, u8 size,
...@@ -96,13 +100,13 @@ static s32 i2c_nuvoton_write_buf(struct i2c_client *client, u8 offset, u8 size, ...@@ -96,13 +100,13 @@ static s32 i2c_nuvoton_write_buf(struct i2c_client *client, u8 offset, u8 size,
/* read TPM_STS register */ /* read TPM_STS register */
static u8 i2c_nuvoton_read_status(struct tpm_chip *chip) static u8 i2c_nuvoton_read_status(struct tpm_chip *chip)
{ {
struct i2c_client *client = to_i2c_client(chip->pdev); struct i2c_client *client = to_i2c_client(chip->dev.parent);
s32 status; s32 status;
u8 data; u8 data;
status = i2c_nuvoton_read_buf(client, TPM_STS, 1, &data); status = i2c_nuvoton_read_buf(client, TPM_STS, 1, &data);
if (status <= 0) { if (status <= 0) {
dev_err(chip->pdev, "%s() error return %d\n", __func__, dev_err(&chip->dev, "%s() error return %d\n", __func__,
status); status);
data = TPM_STS_ERR_VAL; data = TPM_STS_ERR_VAL;
} }
...@@ -127,13 +131,13 @@ static s32 i2c_nuvoton_write_status(struct i2c_client *client, u8 data) ...@@ -127,13 +131,13 @@ static s32 i2c_nuvoton_write_status(struct i2c_client *client, u8 data)
/* write commandReady to TPM_STS register */ /* write commandReady to TPM_STS register */
static void i2c_nuvoton_ready(struct tpm_chip *chip) static void i2c_nuvoton_ready(struct tpm_chip *chip)
{ {
struct i2c_client *client = to_i2c_client(chip->pdev); struct i2c_client *client = to_i2c_client(chip->dev.parent);
s32 status; s32 status;
/* this causes the current command to be aborted */ /* this causes the current command to be aborted */
status = i2c_nuvoton_write_status(client, TPM_STS_COMMAND_READY); status = i2c_nuvoton_write_status(client, TPM_STS_COMMAND_READY);
if (status < 0) if (status < 0)
dev_err(chip->pdev, dev_err(&chip->dev,
"%s() fail to write TPM_STS.commandReady\n", __func__); "%s() fail to write TPM_STS.commandReady\n", __func__);
} }
...@@ -142,7 +146,7 @@ static void i2c_nuvoton_ready(struct tpm_chip *chip) ...@@ -142,7 +146,7 @@ static void i2c_nuvoton_ready(struct tpm_chip *chip)
static int i2c_nuvoton_get_burstcount(struct i2c_client *client, static int i2c_nuvoton_get_burstcount(struct i2c_client *client,
struct tpm_chip *chip) struct tpm_chip *chip)
{ {
unsigned long stop = jiffies + chip->vendor.timeout_d; unsigned long stop = jiffies + chip->timeout_d;
s32 status; s32 status;
int burst_count = -1; int burst_count = -1;
u8 data; u8 data;
...@@ -163,7 +167,7 @@ static int i2c_nuvoton_get_burstcount(struct i2c_client *client, ...@@ -163,7 +167,7 @@ static int i2c_nuvoton_get_burstcount(struct i2c_client *client,
} }
/* /*
* WPCT301/NPCT501 SINT# supports only dataAvail * WPCT301/NPCT501/NPCT6XX SINT# supports only dataAvail
* any call to this function which is not waiting for dataAvail will * any call to this function which is not waiting for dataAvail will
* set queue to NULL to avoid waiting for interrupt * set queue to NULL to avoid waiting for interrupt
*/ */
...@@ -176,12 +180,12 @@ static bool i2c_nuvoton_check_status(struct tpm_chip *chip, u8 mask, u8 value) ...@@ -176,12 +180,12 @@ static bool i2c_nuvoton_check_status(struct tpm_chip *chip, u8 mask, u8 value)
static int i2c_nuvoton_wait_for_stat(struct tpm_chip *chip, u8 mask, u8 value, static int i2c_nuvoton_wait_for_stat(struct tpm_chip *chip, u8 mask, u8 value,
u32 timeout, wait_queue_head_t *queue) u32 timeout, wait_queue_head_t *queue)
{ {
if (chip->vendor.irq && queue) { if ((chip->flags & TPM_CHIP_FLAG_IRQ) && queue) {
s32 rc; s32 rc;
struct priv_data *priv = chip->vendor.priv; struct priv_data *priv = dev_get_drvdata(&chip->dev);
unsigned int cur_intrs = priv->intrs; unsigned int cur_intrs = priv->intrs;
enable_irq(chip->vendor.irq); enable_irq(priv->irq);
rc = wait_event_interruptible_timeout(*queue, rc = wait_event_interruptible_timeout(*queue,
cur_intrs != priv->intrs, cur_intrs != priv->intrs,
timeout); timeout);
...@@ -212,7 +216,7 @@ static int i2c_nuvoton_wait_for_stat(struct tpm_chip *chip, u8 mask, u8 value, ...@@ -212,7 +216,7 @@ static int i2c_nuvoton_wait_for_stat(struct tpm_chip *chip, u8 mask, u8 value,
return 0; return 0;
} while (time_before(jiffies, stop)); } while (time_before(jiffies, stop));
} }
dev_err(chip->pdev, "%s(%02x, %02x) -> timeout\n", __func__, mask, dev_err(&chip->dev, "%s(%02x, %02x) -> timeout\n", __func__, mask,
value); value);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
...@@ -231,16 +235,17 @@ static int i2c_nuvoton_wait_for_data_avail(struct tpm_chip *chip, u32 timeout, ...@@ -231,16 +235,17 @@ static int i2c_nuvoton_wait_for_data_avail(struct tpm_chip *chip, u32 timeout,
static int i2c_nuvoton_recv_data(struct i2c_client *client, static int i2c_nuvoton_recv_data(struct i2c_client *client,
struct tpm_chip *chip, u8 *buf, size_t count) struct tpm_chip *chip, u8 *buf, size_t count)
{ {
struct priv_data *priv = dev_get_drvdata(&chip->dev);
s32 rc; s32 rc;
int burst_count, bytes2read, size = 0; int burst_count, bytes2read, size = 0;
while (size < count && while (size < count &&
i2c_nuvoton_wait_for_data_avail(chip, i2c_nuvoton_wait_for_data_avail(chip,
chip->vendor.timeout_c, chip->timeout_c,
&chip->vendor.read_queue) == 0) { &priv->read_queue) == 0) {
burst_count = i2c_nuvoton_get_burstcount(client, chip); burst_count = i2c_nuvoton_get_burstcount(client, chip);
if (burst_count < 0) { if (burst_count < 0) {
dev_err(chip->pdev, dev_err(&chip->dev,
"%s() fail to read burstCount=%d\n", __func__, "%s() fail to read burstCount=%d\n", __func__,
burst_count); burst_count);
return -EIO; return -EIO;
...@@ -249,12 +254,12 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client, ...@@ -249,12 +254,12 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client,
rc = i2c_nuvoton_read_buf(client, TPM_DATA_FIFO_R, rc = i2c_nuvoton_read_buf(client, TPM_DATA_FIFO_R,
bytes2read, &buf[size]); bytes2read, &buf[size]);
if (rc < 0) { if (rc < 0) {
dev_err(chip->pdev, dev_err(&chip->dev,
"%s() fail on i2c_nuvoton_read_buf()=%d\n", "%s() fail on i2c_nuvoton_read_buf()=%d\n",
__func__, rc); __func__, rc);
return -EIO; return -EIO;
} }
dev_dbg(chip->pdev, "%s(%d):", __func__, bytes2read); dev_dbg(&chip->dev, "%s(%d):", __func__, bytes2read);
size += bytes2read; size += bytes2read;
} }
...@@ -264,7 +269,8 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client, ...@@ -264,7 +269,8 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client,
/* Read TPM command results */ /* Read TPM command results */
static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{ {
struct device *dev = chip->pdev; struct priv_data *priv = dev_get_drvdata(&chip->dev);
struct device *dev = chip->dev.parent;
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
s32 rc; s32 rc;
int expected, status, burst_count, retries, size = 0; int expected, status, burst_count, retries, size = 0;
...@@ -285,7 +291,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -285,7 +291,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
* tag, paramsize, and result * tag, paramsize, and result
*/ */
status = i2c_nuvoton_wait_for_data_avail( status = i2c_nuvoton_wait_for_data_avail(
chip, chip->vendor.timeout_c, &chip->vendor.read_queue); chip, chip->timeout_c, &priv->read_queue);
if (status != 0) { if (status != 0) {
dev_err(dev, "%s() timeout on dataAvail\n", __func__); dev_err(dev, "%s() timeout on dataAvail\n", __func__);
size = -ETIMEDOUT; size = -ETIMEDOUT;
...@@ -325,7 +331,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -325,7 +331,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
} }
if (i2c_nuvoton_wait_for_stat( if (i2c_nuvoton_wait_for_stat(
chip, TPM_STS_VALID | TPM_STS_DATA_AVAIL, chip, TPM_STS_VALID | TPM_STS_DATA_AVAIL,
TPM_STS_VALID, chip->vendor.timeout_c, TPM_STS_VALID, chip->timeout_c,
NULL)) { NULL)) {
dev_err(dev, "%s() error left over data\n", __func__); dev_err(dev, "%s() error left over data\n", __func__);
size = -ETIMEDOUT; size = -ETIMEDOUT;
...@@ -334,7 +340,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -334,7 +340,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
break; break;
} }
i2c_nuvoton_ready(chip); i2c_nuvoton_ready(chip);
dev_dbg(chip->pdev, "%s() -> %d\n", __func__, size); dev_dbg(&chip->dev, "%s() -> %d\n", __func__, size);
return size; return size;
} }
...@@ -347,7 +353,8 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -347,7 +353,8 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
*/ */
static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len) static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
{ {
struct device *dev = chip->pdev; struct priv_data *priv = dev_get_drvdata(&chip->dev);
struct device *dev = chip->dev.parent;
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
u32 ordinal; u32 ordinal;
size_t count = 0; size_t count = 0;
...@@ -357,7 +364,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -357,7 +364,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
i2c_nuvoton_ready(chip); i2c_nuvoton_ready(chip);
if (i2c_nuvoton_wait_for_stat(chip, TPM_STS_COMMAND_READY, if (i2c_nuvoton_wait_for_stat(chip, TPM_STS_COMMAND_READY,
TPM_STS_COMMAND_READY, TPM_STS_COMMAND_READY,
chip->vendor.timeout_b, NULL)) { chip->timeout_b, NULL)) {
dev_err(dev, "%s() timeout on commandReady\n", dev_err(dev, "%s() timeout on commandReady\n",
__func__); __func__);
rc = -EIO; rc = -EIO;
...@@ -389,7 +396,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -389,7 +396,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
TPM_STS_EXPECT, TPM_STS_EXPECT,
TPM_STS_VALID | TPM_STS_VALID |
TPM_STS_EXPECT, TPM_STS_EXPECT,
chip->vendor.timeout_c, chip->timeout_c,
NULL); NULL);
if (rc < 0) { if (rc < 0) {
dev_err(dev, "%s() timeout on Expect\n", dev_err(dev, "%s() timeout on Expect\n",
...@@ -414,7 +421,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -414,7 +421,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
rc = i2c_nuvoton_wait_for_stat(chip, rc = i2c_nuvoton_wait_for_stat(chip,
TPM_STS_VALID | TPM_STS_EXPECT, TPM_STS_VALID | TPM_STS_EXPECT,
TPM_STS_VALID, TPM_STS_VALID,
chip->vendor.timeout_c, NULL); chip->timeout_c, NULL);
if (rc) { if (rc) {
dev_err(dev, "%s() timeout on Expect to clear\n", dev_err(dev, "%s() timeout on Expect to clear\n",
__func__); __func__);
...@@ -439,7 +446,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len) ...@@ -439,7 +446,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
rc = i2c_nuvoton_wait_for_data_avail(chip, rc = i2c_nuvoton_wait_for_data_avail(chip,
tpm_calc_ordinal_duration(chip, tpm_calc_ordinal_duration(chip,
ordinal), ordinal),
&chip->vendor.read_queue); &priv->read_queue);
if (rc) { if (rc) {
dev_err(dev, "%s() timeout command duration\n", __func__); dev_err(dev, "%s() timeout command duration\n", __func__);
i2c_nuvoton_ready(chip); i2c_nuvoton_ready(chip);
...@@ -456,6 +463,7 @@ static bool i2c_nuvoton_req_canceled(struct tpm_chip *chip, u8 status) ...@@ -456,6 +463,7 @@ static bool i2c_nuvoton_req_canceled(struct tpm_chip *chip, u8 status)
} }
static const struct tpm_class_ops tpm_i2c = { static const struct tpm_class_ops tpm_i2c = {
.flags = TPM_OPS_AUTO_STARTUP,
.status = i2c_nuvoton_read_status, .status = i2c_nuvoton_read_status,
.recv = i2c_nuvoton_recv, .recv = i2c_nuvoton_recv,
.send = i2c_nuvoton_send, .send = i2c_nuvoton_send,
...@@ -473,11 +481,11 @@ static const struct tpm_class_ops tpm_i2c = { ...@@ -473,11 +481,11 @@ static const struct tpm_class_ops tpm_i2c = {
static irqreturn_t i2c_nuvoton_int_handler(int dummy, void *dev_id) static irqreturn_t i2c_nuvoton_int_handler(int dummy, void *dev_id)
{ {
struct tpm_chip *chip = dev_id; struct tpm_chip *chip = dev_id;
struct priv_data *priv = chip->vendor.priv; struct priv_data *priv = dev_get_drvdata(&chip->dev);
priv->intrs++; priv->intrs++;
wake_up(&chip->vendor.read_queue); wake_up(&priv->read_queue);
disable_irq_nosync(chip->vendor.irq); disable_irq_nosync(priv->irq);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -521,6 +529,7 @@ static int i2c_nuvoton_probe(struct i2c_client *client, ...@@ -521,6 +529,7 @@ static int i2c_nuvoton_probe(struct i2c_client *client,
int rc; int rc;
struct tpm_chip *chip; struct tpm_chip *chip;
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct priv_data *priv;
u32 vid = 0; u32 vid = 0;
rc = get_vid(client, &vid); rc = get_vid(client, &vid);
...@@ -534,46 +543,56 @@ static int i2c_nuvoton_probe(struct i2c_client *client, ...@@ -534,46 +543,56 @@ static int i2c_nuvoton_probe(struct i2c_client *client,
if (IS_ERR(chip)) if (IS_ERR(chip))
return PTR_ERR(chip); return PTR_ERR(chip);
chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data), priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL);
GFP_KERNEL); if (!priv)
if (!chip->vendor.priv)
return -ENOMEM; return -ENOMEM;
init_waitqueue_head(&chip->vendor.read_queue); if (dev->of_node) {
init_waitqueue_head(&chip->vendor.int_queue); const struct of_device_id *of_id;
of_id = of_match_device(dev->driver->of_match_table, dev);
if (of_id && of_id->data == OF_IS_TPM2)
chip->flags |= TPM_CHIP_FLAG_TPM2;
} else
if (id->driver_data == I2C_IS_TPM2)
chip->flags |= TPM_CHIP_FLAG_TPM2;
init_waitqueue_head(&priv->read_queue);
/* Default timeouts */ /* Default timeouts */
chip->vendor.timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); chip->timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
chip->vendor.timeout_b = msecs_to_jiffies(TPM_I2C_LONG_TIMEOUT); chip->timeout_b = msecs_to_jiffies(TPM_I2C_LONG_TIMEOUT);
chip->vendor.timeout_c = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); chip->timeout_c = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
chip->vendor.timeout_d = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); chip->timeout_d = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
dev_set_drvdata(&chip->dev, priv);
/* /*
* I2C intfcaps (interrupt capabilitieis) in the chip are hard coded to: * I2C intfcaps (interrupt capabilitieis) in the chip are hard coded to:
* TPM_INTF_INT_LEVEL_LOW | TPM_INTF_DATA_AVAIL_INT * TPM_INTF_INT_LEVEL_LOW | TPM_INTF_DATA_AVAIL_INT
* The IRQ should be set in the i2c_board_info (which is done * The IRQ should be set in the i2c_board_info (which is done
* automatically in of_i2c_register_devices, for device tree users */ * automatically in of_i2c_register_devices, for device tree users */
chip->vendor.irq = client->irq; priv->irq = client->irq;
if (client->irq) {
if (chip->vendor.irq) { dev_dbg(dev, "%s() priv->irq\n", __func__);
dev_dbg(dev, "%s() chip-vendor.irq\n", __func__); rc = devm_request_irq(dev, client->irq,
rc = devm_request_irq(dev, chip->vendor.irq,
i2c_nuvoton_int_handler, i2c_nuvoton_int_handler,
IRQF_TRIGGER_LOW, IRQF_TRIGGER_LOW,
chip->devname, dev_name(&chip->dev),
chip); chip);
if (rc) { if (rc) {
dev_err(dev, "%s() Unable to request irq: %d for use\n", dev_err(dev, "%s() Unable to request irq: %d for use\n",
__func__, chip->vendor.irq); __func__, priv->irq);
chip->vendor.irq = 0; priv->irq = 0;
} else { } else {
chip->flags |= TPM_CHIP_FLAG_IRQ;
/* Clear any pending interrupt */ /* Clear any pending interrupt */
i2c_nuvoton_ready(chip); i2c_nuvoton_ready(chip);
/* - wait for TPM_STS==0xA0 (stsValid, commandReady) */ /* - wait for TPM_STS==0xA0 (stsValid, commandReady) */
rc = i2c_nuvoton_wait_for_stat(chip, rc = i2c_nuvoton_wait_for_stat(chip,
TPM_STS_COMMAND_READY, TPM_STS_COMMAND_READY,
TPM_STS_COMMAND_READY, TPM_STS_COMMAND_READY,
chip->vendor.timeout_b, chip->timeout_b,
NULL); NULL);
if (rc == 0) { if (rc == 0) {
/* /*
...@@ -601,25 +620,20 @@ static int i2c_nuvoton_probe(struct i2c_client *client, ...@@ -601,25 +620,20 @@ static int i2c_nuvoton_probe(struct i2c_client *client,
} }
} }
if (tpm_get_timeouts(chip))
return -ENODEV;
if (tpm_do_selftest(chip))
return -ENODEV;
return tpm_chip_register(chip); return tpm_chip_register(chip);
} }
static int i2c_nuvoton_remove(struct i2c_client *client) static int i2c_nuvoton_remove(struct i2c_client *client)
{ {
struct device *dev = &(client->dev); struct tpm_chip *chip = i2c_get_clientdata(client);
struct tpm_chip *chip = dev_get_drvdata(dev);
tpm_chip_unregister(chip); tpm_chip_unregister(chip);
return 0; return 0;
} }
static const struct i2c_device_id i2c_nuvoton_id[] = { static const struct i2c_device_id i2c_nuvoton_id[] = {
{I2C_DRIVER_NAME, 0}, {"tpm_i2c_nuvoton"},
{"tpm2_i2c_nuvoton", .driver_data = I2C_IS_TPM2},
{} {}
}; };
MODULE_DEVICE_TABLE(i2c, i2c_nuvoton_id); MODULE_DEVICE_TABLE(i2c, i2c_nuvoton_id);
...@@ -628,6 +642,7 @@ MODULE_DEVICE_TABLE(i2c, i2c_nuvoton_id); ...@@ -628,6 +642,7 @@ MODULE_DEVICE_TABLE(i2c, i2c_nuvoton_id);
static const struct of_device_id i2c_nuvoton_of_match[] = { static const struct of_device_id i2c_nuvoton_of_match[] = {
{.compatible = "nuvoton,npct501"}, {.compatible = "nuvoton,npct501"},
{.compatible = "winbond,wpct301"}, {.compatible = "winbond,wpct301"},
{.compatible = "nuvoton,npct601", .data = OF_IS_TPM2},
{}, {},
}; };
MODULE_DEVICE_TABLE(of, i2c_nuvoton_of_match); MODULE_DEVICE_TABLE(of, i2c_nuvoton_of_match);
...@@ -640,7 +655,7 @@ static struct i2c_driver i2c_nuvoton_driver = { ...@@ -640,7 +655,7 @@ static struct i2c_driver i2c_nuvoton_driver = {
.probe = i2c_nuvoton_probe, .probe = i2c_nuvoton_probe,
.remove = i2c_nuvoton_remove, .remove = i2c_nuvoton_remove,
.driver = { .driver = {
.name = I2C_DRIVER_NAME, .name = "tpm_i2c_nuvoton",
.pm = &i2c_nuvoton_pm_ops, .pm = &i2c_nuvoton_pm_ops,
.of_match_table = of_match_ptr(i2c_nuvoton_of_match), .of_match_table = of_match_ptr(i2c_nuvoton_of_match),
}, },
......
...@@ -53,21 +53,6 @@ static int ibmvtpm_send_crq(struct vio_dev *vdev, u64 w1, u64 w2) ...@@ -53,21 +53,6 @@ static int ibmvtpm_send_crq(struct vio_dev *vdev, u64 w1, u64 w2)
return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, w1, w2); return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, w1, w2);
} }
/**
* 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 * tpm_ibmvtpm_recv - Receive data after send
* @chip: tpm chip struct * @chip: tpm chip struct
...@@ -79,12 +64,10 @@ static struct ibmvtpm_dev *ibmvtpm_get_data(const struct device *dev) ...@@ -79,12 +64,10 @@ static struct ibmvtpm_dev *ibmvtpm_get_data(const struct device *dev)
*/ */
static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count) static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{ {
struct ibmvtpm_dev *ibmvtpm; struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
u16 len; u16 len;
int sig; int sig;
ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
if (!ibmvtpm->rtce_buf) { if (!ibmvtpm->rtce_buf) {
dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n"); dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
return 0; return 0;
...@@ -122,13 +105,11 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count) ...@@ -122,13 +105,11 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
*/ */
static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
{ {
struct ibmvtpm_dev *ibmvtpm; struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
struct ibmvtpm_crq crq; struct ibmvtpm_crq crq;
__be64 *word = (__be64 *)&crq; __be64 *word = (__be64 *)&crq;
int rc, sig; int rc, sig;
ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
if (!ibmvtpm->rtce_buf) { if (!ibmvtpm->rtce_buf) {
dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n"); dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
return 0; return 0;
...@@ -289,8 +270,8 @@ static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm) ...@@ -289,8 +270,8 @@ static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
*/ */
static int tpm_ibmvtpm_remove(struct vio_dev *vdev) static int tpm_ibmvtpm_remove(struct vio_dev *vdev)
{ {
struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev); struct tpm_chip *chip = dev_get_drvdata(&vdev->dev);
struct tpm_chip *chip = dev_get_drvdata(ibmvtpm->dev); struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
int rc = 0; int rc = 0;
tpm_chip_unregister(chip); tpm_chip_unregister(chip);
...@@ -327,7 +308,8 @@ static int tpm_ibmvtpm_remove(struct vio_dev *vdev) ...@@ -327,7 +308,8 @@ static int tpm_ibmvtpm_remove(struct vio_dev *vdev)
*/ */
static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev) static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev)
{ {
struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev); struct tpm_chip *chip = dev_get_drvdata(&vdev->dev);
struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
/* ibmvtpm initializes at probe time, so the data we are /* ibmvtpm initializes at probe time, so the data we are
* asking for may not be set yet. Estimate that 4K required * asking for may not be set yet. Estimate that 4K required
...@@ -348,7 +330,8 @@ static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev) ...@@ -348,7 +330,8 @@ static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev)
*/ */
static int tpm_ibmvtpm_suspend(struct device *dev) static int tpm_ibmvtpm_suspend(struct device *dev)
{ {
struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev); struct tpm_chip *chip = dev_get_drvdata(dev);
struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
struct ibmvtpm_crq crq; struct ibmvtpm_crq crq;
u64 *buf = (u64 *) &crq; u64 *buf = (u64 *) &crq;
int rc = 0; int rc = 0;
...@@ -400,7 +383,8 @@ static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm) ...@@ -400,7 +383,8 @@ static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm)
*/ */
static int tpm_ibmvtpm_resume(struct device *dev) static int tpm_ibmvtpm_resume(struct device *dev)
{ {
struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev); struct tpm_chip *chip = dev_get_drvdata(dev);
struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
int rc = 0; int rc = 0;
do { do {
...@@ -643,7 +627,7 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, ...@@ -643,7 +627,7 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
crq_q->index = 0; crq_q->index = 0;
TPM_VPRIV(chip) = (void *)ibmvtpm; dev_set_drvdata(&chip->dev, ibmvtpm);
spin_lock_init(&ibmvtpm->rtce_lock); spin_lock_init(&ibmvtpm->rtce_lock);
......
...@@ -195,9 +195,9 @@ static int wait(struct tpm_chip *chip, int wait_for_bit) ...@@ -195,9 +195,9 @@ static int wait(struct tpm_chip *chip, int wait_for_bit)
} }
if (i == TPM_MAX_TRIES) { /* timeout occurs */ if (i == TPM_MAX_TRIES) { /* timeout occurs */
if (wait_for_bit == STAT_XFE) if (wait_for_bit == STAT_XFE)
dev_err(chip->pdev, "Timeout in wait(STAT_XFE)\n"); dev_err(&chip->dev, "Timeout in wait(STAT_XFE)\n");
if (wait_for_bit == STAT_RDA) if (wait_for_bit == STAT_RDA)
dev_err(chip->pdev, "Timeout in wait(STAT_RDA)\n"); dev_err(&chip->dev, "Timeout in wait(STAT_RDA)\n");
return -EIO; return -EIO;
} }
return 0; return 0;
...@@ -220,7 +220,7 @@ static void wait_and_send(struct tpm_chip *chip, u8 sendbyte) ...@@ -220,7 +220,7 @@ static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
static void tpm_wtx(struct tpm_chip *chip) static void tpm_wtx(struct tpm_chip *chip)
{ {
number_of_wtx++; number_of_wtx++;
dev_info(chip->pdev, "Granting WTX (%02d / %02d)\n", dev_info(&chip->dev, "Granting WTX (%02d / %02d)\n",
number_of_wtx, TPM_MAX_WTX_PACKAGES); number_of_wtx, TPM_MAX_WTX_PACKAGES);
wait_and_send(chip, TPM_VL_VER); wait_and_send(chip, TPM_VL_VER);
wait_and_send(chip, TPM_CTRL_WTX); wait_and_send(chip, TPM_CTRL_WTX);
...@@ -231,7 +231,7 @@ static void tpm_wtx(struct tpm_chip *chip) ...@@ -231,7 +231,7 @@ static void tpm_wtx(struct tpm_chip *chip)
static void tpm_wtx_abort(struct tpm_chip *chip) static void tpm_wtx_abort(struct tpm_chip *chip)
{ {
dev_info(chip->pdev, "Aborting WTX\n"); dev_info(&chip->dev, "Aborting WTX\n");
wait_and_send(chip, TPM_VL_VER); wait_and_send(chip, TPM_VL_VER);
wait_and_send(chip, TPM_CTRL_WTX_ABORT); wait_and_send(chip, TPM_CTRL_WTX_ABORT);
wait_and_send(chip, 0x00); wait_and_send(chip, 0x00);
...@@ -257,7 +257,7 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count) ...@@ -257,7 +257,7 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
} }
if (buf[0] != TPM_VL_VER) { if (buf[0] != TPM_VL_VER) {
dev_err(chip->pdev, dev_err(&chip->dev,
"Wrong transport protocol implementation!\n"); "Wrong transport protocol implementation!\n");
return -EIO; return -EIO;
} }
...@@ -272,7 +272,7 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count) ...@@ -272,7 +272,7 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
} }
if ((size == 0x6D00) && (buf[1] == 0x80)) { if ((size == 0x6D00) && (buf[1] == 0x80)) {
dev_err(chip->pdev, "Error handling on vendor layer!\n"); dev_err(&chip->dev, "Error handling on vendor layer!\n");
return -EIO; return -EIO;
} }
...@@ -284,7 +284,7 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count) ...@@ -284,7 +284,7 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
} }
if (buf[1] == TPM_CTRL_WTX) { if (buf[1] == TPM_CTRL_WTX) {
dev_info(chip->pdev, "WTX-package received\n"); dev_info(&chip->dev, "WTX-package received\n");
if (number_of_wtx < TPM_MAX_WTX_PACKAGES) { if (number_of_wtx < TPM_MAX_WTX_PACKAGES) {
tpm_wtx(chip); tpm_wtx(chip);
goto recv_begin; goto recv_begin;
...@@ -295,14 +295,14 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count) ...@@ -295,14 +295,14 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
} }
if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) { if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) {
dev_info(chip->pdev, "WTX-abort acknowledged\n"); dev_info(&chip->dev, "WTX-abort acknowledged\n");
return size; return size;
} }
if (buf[1] == TPM_CTRL_ERROR) { if (buf[1] == TPM_CTRL_ERROR) {
dev_err(chip->pdev, "ERROR-package received:\n"); dev_err(&chip->dev, "ERROR-package received:\n");
if (buf[4] == TPM_INF_NAK) if (buf[4] == TPM_INF_NAK)
dev_err(chip->pdev, dev_err(&chip->dev,
"-> Negative acknowledgement" "-> Negative acknowledgement"
" - retransmit command!\n"); " - retransmit command!\n");
return -EIO; return -EIO;
...@@ -321,7 +321,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count) ...@@ -321,7 +321,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
ret = empty_fifo(chip, 1); ret = empty_fifo(chip, 1);
if (ret) { if (ret) {
dev_err(chip->pdev, "Timeout while clearing FIFO\n"); dev_err(&chip->dev, "Timeout while clearing FIFO\n");
return -EIO; return -EIO;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment