mirror of
https://github.com/torvalds/linux.git
synced 2024-12-04 18:13:04 +00:00
Hi,
This pull request has only some minor tweaks. BR, Jarkko -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQRE6pSOnaBC00OEHEIaerohdGur0gUCZz+7VQAKCRAaerohdGur 0up2AQCVWdhQq3JdGyU6CHEz28ZrcFCR5Mlwr6XHhtXeDb/jlAEA1CjVtSFho2ir bfaTfirN7RWEFdZyDpzqwROYu03rfwg= =cm2z -----END PGP SIGNATURE----- Merge tag 'tpmdd-next-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd Pull TPM updates from Jarkko Sakkinen: "Only some minor tweaks" * tag 'tpmdd-next-6.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd: tpm: atmel: Drop PPC64 specific MMIO setup char: tpm: cr50: Add new device/vendor ID 0x50666666 char: tpm: cr50: Move i2c locking to request/relinquish locality ops char: tpm: cr50: Use generic request/relinquish locality ops tpm: ibmvtpm: Set TPM_OPS_AUTO_STARTUP flag on driver
This commit is contained in:
commit
619d996c86
@ -162,7 +162,7 @@ config TCG_NSC
|
||||
|
||||
config TCG_ATMEL
|
||||
tristate "Atmel TPM Interface"
|
||||
depends on PPC64 || HAS_IOPORT_MAP
|
||||
depends on HAS_IOPORT_MAP
|
||||
depends on HAS_IOPORT
|
||||
help
|
||||
If you have a TPM security chip from Atmel say Yes and it
|
||||
|
@ -1390,5 +1390,4 @@ int tpm2_sessions_init(struct tpm_chip *chip)
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(tpm2_sessions_init);
|
||||
#endif /* CONFIG_TCG_TPM2_HMAC */
|
||||
|
@ -15,7 +15,66 @@
|
||||
*/
|
||||
|
||||
#include "tpm.h"
|
||||
#include "tpm_atmel.h"
|
||||
|
||||
struct tpm_atmel_priv {
|
||||
int region_size;
|
||||
int have_region;
|
||||
unsigned long base;
|
||||
void __iomem *iobase;
|
||||
};
|
||||
|
||||
#define atmel_getb(chip, offset) inb(atmel_get_priv(chip)->base + (offset))
|
||||
#define atmel_putb(val, chip, offset) \
|
||||
outb(val, atmel_get_priv(chip)->base + (offset))
|
||||
#define atmel_request_region request_region
|
||||
#define atmel_release_region release_region
|
||||
/* Atmel definitions */
|
||||
enum tpm_atmel_addr {
|
||||
TPM_ATMEL_BASE_ADDR_LO = 0x08,
|
||||
TPM_ATMEL_BASE_ADDR_HI = 0x09
|
||||
};
|
||||
|
||||
static inline int tpm_read_index(int base, int index)
|
||||
{
|
||||
outb(index, base);
|
||||
return inb(base + 1) & 0xFF;
|
||||
}
|
||||
|
||||
/* Verify this is a 1.1 Atmel TPM */
|
||||
static int atmel_verify_tpm11(void)
|
||||
{
|
||||
/* verify that it is an Atmel part */
|
||||
if (tpm_read_index(TPM_ADDR, 4) != 'A' ||
|
||||
tpm_read_index(TPM_ADDR, 5) != 'T' ||
|
||||
tpm_read_index(TPM_ADDR, 6) != 'M' ||
|
||||
tpm_read_index(TPM_ADDR, 7) != 'L')
|
||||
return 1;
|
||||
|
||||
/* query chip for its version number */
|
||||
if (tpm_read_index(TPM_ADDR, 0x00) != 1 ||
|
||||
tpm_read_index(TPM_ADDR, 0x01) != 1)
|
||||
return 1;
|
||||
|
||||
/* This is an atmel supported part */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Determine where to talk to device */
|
||||
static void __iomem *atmel_get_base_addr(unsigned long *base, int *region_size)
|
||||
{
|
||||
int lo, hi;
|
||||
|
||||
if (atmel_verify_tpm11() != 0)
|
||||
return NULL;
|
||||
|
||||
lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
|
||||
hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
|
||||
|
||||
*base = (hi << 8) | lo;
|
||||
*region_size = 2;
|
||||
|
||||
return ioport_map(*base, *region_size);
|
||||
}
|
||||
|
||||
/* write status bits */
|
||||
enum tpm_atmel_write_status {
|
||||
@ -142,7 +201,6 @@ static void atml_plat_remove(void)
|
||||
tpm_chip_unregister(chip);
|
||||
if (priv->have_region)
|
||||
atmel_release_region(priv->base, priv->region_size);
|
||||
atmel_put_base_addr(priv->iobase);
|
||||
platform_device_unregister(pdev);
|
||||
}
|
||||
|
||||
@ -211,7 +269,6 @@ static int __init init_atmel(void)
|
||||
err_unreg_dev:
|
||||
platform_device_unregister(pdev);
|
||||
err_rel_reg:
|
||||
atmel_put_base_addr(iobase);
|
||||
if (have_region)
|
||||
atmel_release_region(base,
|
||||
region_size);
|
||||
|
@ -1,140 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2005 IBM Corporation
|
||||
*
|
||||
* Authors:
|
||||
* Kylene Hall <kjhall@us.ibm.com>
|
||||
*
|
||||
* Maintained by: <tpmdd-devel@lists.sourceforge.net>
|
||||
*
|
||||
* Device driver for TCG/TCPA TPM (trusted platform module).
|
||||
* Specifications at www.trustedcomputinggroup.org
|
||||
*
|
||||
* These difference are required on power because the device must be
|
||||
* discovered through the device tree and iomap must be used to get
|
||||
* around the need for holes in the io_page_mask. This does not happen
|
||||
* automatically because the tpm is not a normal pci device and lives
|
||||
* under the root node.
|
||||
*/
|
||||
|
||||
struct tpm_atmel_priv {
|
||||
int region_size;
|
||||
int have_region;
|
||||
unsigned long base;
|
||||
void __iomem *iobase;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
|
||||
#include <linux/of.h>
|
||||
|
||||
#define atmel_getb(priv, offset) readb(priv->iobase + offset)
|
||||
#define atmel_putb(val, priv, offset) writeb(val, priv->iobase + offset)
|
||||
#define atmel_request_region request_mem_region
|
||||
#define atmel_release_region release_mem_region
|
||||
|
||||
static inline void atmel_put_base_addr(void __iomem *iobase)
|
||||
{
|
||||
iounmap(iobase);
|
||||
}
|
||||
|
||||
static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
|
||||
{
|
||||
struct device_node *dn;
|
||||
unsigned long address, size;
|
||||
const unsigned int *reg;
|
||||
int reglen;
|
||||
int naddrc;
|
||||
int nsizec;
|
||||
|
||||
dn = of_find_node_by_name(NULL, "tpm");
|
||||
|
||||
if (!dn)
|
||||
return NULL;
|
||||
|
||||
if (!of_device_is_compatible(dn, "AT97SC3201")) {
|
||||
of_node_put(dn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
reg = of_get_property(dn, "reg", ®len);
|
||||
naddrc = of_n_addr_cells(dn);
|
||||
nsizec = of_n_size_cells(dn);
|
||||
|
||||
of_node_put(dn);
|
||||
|
||||
|
||||
if (naddrc == 2)
|
||||
address = ((unsigned long) reg[0] << 32) | reg[1];
|
||||
else
|
||||
address = reg[0];
|
||||
|
||||
if (nsizec == 2)
|
||||
size =
|
||||
((unsigned long) reg[naddrc] << 32) | reg[naddrc + 1];
|
||||
else
|
||||
size = reg[naddrc];
|
||||
|
||||
*base = address;
|
||||
*region_size = size;
|
||||
return ioremap(*base, *region_size);
|
||||
}
|
||||
#else
|
||||
#define atmel_getb(chip, offset) inb(atmel_get_priv(chip)->base + offset)
|
||||
#define atmel_putb(val, chip, offset) \
|
||||
outb(val, atmel_get_priv(chip)->base + offset)
|
||||
#define atmel_request_region request_region
|
||||
#define atmel_release_region release_region
|
||||
/* Atmel definitions */
|
||||
enum tpm_atmel_addr {
|
||||
TPM_ATMEL_BASE_ADDR_LO = 0x08,
|
||||
TPM_ATMEL_BASE_ADDR_HI = 0x09
|
||||
};
|
||||
|
||||
static inline int tpm_read_index(int base, int index)
|
||||
{
|
||||
outb(index, base);
|
||||
return inb(base+1) & 0xFF;
|
||||
}
|
||||
|
||||
/* Verify this is a 1.1 Atmel TPM */
|
||||
static int atmel_verify_tpm11(void)
|
||||
{
|
||||
|
||||
/* verify that it is an Atmel part */
|
||||
if (tpm_read_index(TPM_ADDR, 4) != 'A' ||
|
||||
tpm_read_index(TPM_ADDR, 5) != 'T' ||
|
||||
tpm_read_index(TPM_ADDR, 6) != 'M' ||
|
||||
tpm_read_index(TPM_ADDR, 7) != 'L')
|
||||
return 1;
|
||||
|
||||
/* query chip for its version number */
|
||||
if (tpm_read_index(TPM_ADDR, 0x00) != 1 ||
|
||||
tpm_read_index(TPM_ADDR, 0x01) != 1)
|
||||
return 1;
|
||||
|
||||
/* This is an atmel supported part */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void atmel_put_base_addr(void __iomem *iobase)
|
||||
{
|
||||
}
|
||||
|
||||
/* Determine where to talk to device */
|
||||
static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
|
||||
{
|
||||
int lo, hi;
|
||||
|
||||
if (atmel_verify_tpm11() != 0)
|
||||
return NULL;
|
||||
|
||||
lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
|
||||
hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
|
||||
|
||||
*base = (hi << 8) | lo;
|
||||
*region_size = 2;
|
||||
|
||||
return ioport_map(*base, *region_size);
|
||||
}
|
||||
#endif
|
@ -450,6 +450,7 @@ static bool tpm_ibmvtpm_req_canceled(struct tpm_chip *chip, u8 status)
|
||||
}
|
||||
|
||||
static const struct tpm_class_ops tpm_ibmvtpm = {
|
||||
.flags = TPM_OPS_AUTO_STARTUP,
|
||||
.recv = tpm_ibmvtpm_recv,
|
||||
.send = tpm_ibmvtpm_send,
|
||||
.cancel = tpm_ibmvtpm_cancel,
|
||||
@ -690,20 +691,6 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
|
||||
if (!strcmp(id->compat, "IBM,vtpm20"))
|
||||
chip->flags |= TPM_CHIP_FLAG_TPM2;
|
||||
|
||||
rc = tpm_get_timeouts(chip);
|
||||
if (rc)
|
||||
goto init_irq_cleanup;
|
||||
|
||||
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
|
||||
rc = tpm2_get_cc_attrs_tbl(chip);
|
||||
if (rc)
|
||||
goto init_irq_cleanup;
|
||||
|
||||
rc = tpm2_sessions_init(chip);
|
||||
if (rc)
|
||||
goto init_irq_cleanup;
|
||||
}
|
||||
|
||||
return tpm_chip_register(chip);
|
||||
init_irq_cleanup:
|
||||
do {
|
||||
|
@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
@ -30,11 +31,13 @@
|
||||
#define TPM_CR50_MAX_BUFSIZE 64
|
||||
#define TPM_CR50_TIMEOUT_SHORT_MS 2 /* Short timeout during transactions */
|
||||
#define TPM_CR50_TIMEOUT_NOIRQ_MS 20 /* Timeout for TPM ready without IRQ */
|
||||
#define TPM_CR50_I2C_DID_VID 0x00281ae0L /* Device and vendor ID reg value */
|
||||
#define TPM_TI50_I2C_DID_VID 0x504a6666L /* Device and vendor ID reg value */
|
||||
#define TPM_CR50_I2C_DID_VID 0x00281ae0L /* Device and vendor ID for Cr50 H1 */
|
||||
#define TPM_TI50_DT_I2C_DID_VID 0x504a6666L /* Device and vendor ID for Ti50 DT */
|
||||
#define TPM_TI50_OT_I2C_DID_VID 0x50666666L /* Device and vendor ID for TI50 OT */
|
||||
#define TPM_CR50_I2C_MAX_RETRIES 3 /* Max retries due to I2C errors */
|
||||
#define TPM_CR50_I2C_RETRY_DELAY_LO 55 /* Min usecs between retries on I2C */
|
||||
#define TPM_CR50_I2C_RETRY_DELAY_HI 65 /* Max usecs between retries on I2C */
|
||||
#define TPM_CR50_I2C_DEFAULT_LOC 0
|
||||
|
||||
#define TPM_I2C_ACCESS(l) (0x0000 | ((l) << 4))
|
||||
#define TPM_I2C_STS(l) (0x0001 | ((l) << 4))
|
||||
@ -199,8 +202,6 @@ static int tpm_cr50_i2c_read(struct tpm_chip *chip, u8 addr, u8 *buffer, size_t
|
||||
};
|
||||
int rc;
|
||||
|
||||
i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
|
||||
|
||||
/* Prepare for completion interrupt */
|
||||
tpm_cr50_i2c_enable_tpm_irq(chip);
|
||||
|
||||
@ -219,7 +220,6 @@ static int tpm_cr50_i2c_read(struct tpm_chip *chip, u8 addr, u8 *buffer, size_t
|
||||
|
||||
out:
|
||||
tpm_cr50_i2c_disable_tpm_irq(chip);
|
||||
i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
|
||||
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
@ -261,8 +261,6 @@ static int tpm_cr50_i2c_write(struct tpm_chip *chip, u8 addr, u8 *buffer,
|
||||
priv->buf[0] = addr;
|
||||
memcpy(priv->buf + 1, buffer, len);
|
||||
|
||||
i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
|
||||
|
||||
/* Prepare for completion interrupt */
|
||||
tpm_cr50_i2c_enable_tpm_irq(chip);
|
||||
|
||||
@ -276,7 +274,6 @@ static int tpm_cr50_i2c_write(struct tpm_chip *chip, u8 addr, u8 *buffer,
|
||||
|
||||
out:
|
||||
tpm_cr50_i2c_disable_tpm_irq(chip);
|
||||
i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
|
||||
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
@ -285,25 +282,26 @@ out:
|
||||
}
|
||||
|
||||
/**
|
||||
* tpm_cr50_check_locality() - Verify TPM locality 0 is active.
|
||||
* tpm_cr50_check_locality() - Verify if required TPM locality is active.
|
||||
* @chip: A TPM chip.
|
||||
* @loc: Locality to be verified
|
||||
*
|
||||
* Return:
|
||||
* - 0: Success.
|
||||
* - loc: Success.
|
||||
* - -errno: A POSIX error code.
|
||||
*/
|
||||
static int tpm_cr50_check_locality(struct tpm_chip *chip)
|
||||
static int tpm_cr50_check_locality(struct tpm_chip *chip, int loc)
|
||||
{
|
||||
u8 mask = TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY;
|
||||
u8 buf;
|
||||
int rc;
|
||||
|
||||
rc = tpm_cr50_i2c_read(chip, TPM_I2C_ACCESS(0), &buf, sizeof(buf));
|
||||
rc = tpm_cr50_i2c_read(chip, TPM_I2C_ACCESS(loc), &buf, sizeof(buf));
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if ((buf & mask) == mask)
|
||||
return 0;
|
||||
return loc;
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
@ -311,53 +309,72 @@ static int tpm_cr50_check_locality(struct tpm_chip *chip)
|
||||
/**
|
||||
* tpm_cr50_release_locality() - Release TPM locality.
|
||||
* @chip: A TPM chip.
|
||||
* @force: Flag to force release if set.
|
||||
*/
|
||||
static void tpm_cr50_release_locality(struct tpm_chip *chip, bool force)
|
||||
{
|
||||
u8 mask = TPM_ACCESS_VALID | TPM_ACCESS_REQUEST_PENDING;
|
||||
u8 addr = TPM_I2C_ACCESS(0);
|
||||
u8 buf;
|
||||
|
||||
if (tpm_cr50_i2c_read(chip, addr, &buf, sizeof(buf)) < 0)
|
||||
return;
|
||||
|
||||
if (force || (buf & mask) == mask) {
|
||||
buf = TPM_ACCESS_ACTIVE_LOCALITY;
|
||||
tpm_cr50_i2c_write(chip, addr, &buf, sizeof(buf));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* tpm_cr50_request_locality() - Request TPM locality 0.
|
||||
* @chip: A TPM chip.
|
||||
* @loc: Locality to be released
|
||||
*
|
||||
* Return:
|
||||
* - 0: Success.
|
||||
* - -errno: A POSIX error code.
|
||||
*/
|
||||
static int tpm_cr50_request_locality(struct tpm_chip *chip)
|
||||
static int tpm_cr50_release_locality(struct tpm_chip *chip, int loc)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(chip->dev.parent);
|
||||
u8 mask = TPM_ACCESS_VALID | TPM_ACCESS_REQUEST_PENDING;
|
||||
u8 addr = TPM_I2C_ACCESS(loc);
|
||||
u8 buf;
|
||||
int rc;
|
||||
|
||||
rc = tpm_cr50_i2c_read(chip, addr, &buf, sizeof(buf));
|
||||
if (rc < 0)
|
||||
goto unlock_out;
|
||||
|
||||
if ((buf & mask) == mask) {
|
||||
buf = TPM_ACCESS_ACTIVE_LOCALITY;
|
||||
rc = tpm_cr50_i2c_write(chip, addr, &buf, sizeof(buf));
|
||||
}
|
||||
|
||||
unlock_out:
|
||||
i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* tpm_cr50_request_locality() - Request TPM locality.
|
||||
* @chip: A TPM chip.
|
||||
* @loc: Locality to be requested.
|
||||
*
|
||||
* Return:
|
||||
* - loc: Success.
|
||||
* - -errno: A POSIX error code.
|
||||
*/
|
||||
static int tpm_cr50_request_locality(struct tpm_chip *chip, int loc)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(chip->dev.parent);
|
||||
u8 buf = TPM_ACCESS_REQUEST_USE;
|
||||
unsigned long stop;
|
||||
int rc;
|
||||
|
||||
if (!tpm_cr50_check_locality(chip))
|
||||
return 0;
|
||||
i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
|
||||
|
||||
rc = tpm_cr50_i2c_write(chip, TPM_I2C_ACCESS(0), &buf, sizeof(buf));
|
||||
if (tpm_cr50_check_locality(chip, loc) == loc)
|
||||
return loc;
|
||||
|
||||
rc = tpm_cr50_i2c_write(chip, TPM_I2C_ACCESS(loc), &buf, sizeof(buf));
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
goto unlock_out;
|
||||
|
||||
stop = jiffies + chip->timeout_a;
|
||||
do {
|
||||
if (!tpm_cr50_check_locality(chip))
|
||||
return 0;
|
||||
if (tpm_cr50_check_locality(chip, loc) == loc)
|
||||
return loc;
|
||||
|
||||
msleep(TPM_CR50_TIMEOUT_SHORT_MS);
|
||||
} while (time_before(jiffies, stop));
|
||||
|
||||
return -ETIMEDOUT;
|
||||
rc = -ETIMEDOUT;
|
||||
|
||||
unlock_out:
|
||||
i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -373,7 +390,7 @@ static u8 tpm_cr50_i2c_tis_status(struct tpm_chip *chip)
|
||||
{
|
||||
u8 buf[4];
|
||||
|
||||
if (tpm_cr50_i2c_read(chip, TPM_I2C_STS(0), buf, sizeof(buf)) < 0)
|
||||
if (tpm_cr50_i2c_read(chip, TPM_I2C_STS(chip->locality), buf, sizeof(buf)) < 0)
|
||||
return 0;
|
||||
|
||||
return buf[0];
|
||||
@ -389,7 +406,7 @@ static void tpm_cr50_i2c_tis_set_ready(struct tpm_chip *chip)
|
||||
{
|
||||
u8 buf[4] = { TPM_STS_COMMAND_READY };
|
||||
|
||||
tpm_cr50_i2c_write(chip, TPM_I2C_STS(0), buf, sizeof(buf));
|
||||
tpm_cr50_i2c_write(chip, TPM_I2C_STS(chip->locality), buf, sizeof(buf));
|
||||
msleep(TPM_CR50_TIMEOUT_SHORT_MS);
|
||||
}
|
||||
|
||||
@ -419,7 +436,7 @@ static int tpm_cr50_i2c_get_burst_and_status(struct tpm_chip *chip, u8 mask,
|
||||
stop = jiffies + chip->timeout_b;
|
||||
|
||||
do {
|
||||
if (tpm_cr50_i2c_read(chip, TPM_I2C_STS(0), buf, sizeof(buf)) < 0) {
|
||||
if (tpm_cr50_i2c_read(chip, TPM_I2C_STS(chip->locality), buf, sizeof(buf)) < 0) {
|
||||
msleep(TPM_CR50_TIMEOUT_SHORT_MS);
|
||||
continue;
|
||||
}
|
||||
@ -453,7 +470,7 @@ static int tpm_cr50_i2c_tis_recv(struct tpm_chip *chip, u8 *buf, size_t buf_len)
|
||||
|
||||
u8 mask = TPM_STS_VALID | TPM_STS_DATA_AVAIL;
|
||||
size_t burstcnt, cur, len, expected;
|
||||
u8 addr = TPM_I2C_DATA_FIFO(0);
|
||||
u8 addr = TPM_I2C_DATA_FIFO(chip->locality);
|
||||
u32 status;
|
||||
int rc;
|
||||
|
||||
@ -515,7 +532,6 @@ static int tpm_cr50_i2c_tis_recv(struct tpm_chip *chip, u8 *buf, size_t buf_len)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
tpm_cr50_release_locality(chip, false);
|
||||
return cur;
|
||||
|
||||
out_err:
|
||||
@ -523,7 +539,6 @@ out_err:
|
||||
if (tpm_cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY)
|
||||
tpm_cr50_i2c_tis_set_ready(chip);
|
||||
|
||||
tpm_cr50_release_locality(chip, false);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -545,10 +560,6 @@ static int tpm_cr50_i2c_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
|
||||
u32 status;
|
||||
int rc;
|
||||
|
||||
rc = tpm_cr50_request_locality(chip);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* Wait until TPM is ready for a command */
|
||||
stop = jiffies + chip->timeout_b;
|
||||
while (!(tpm_cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY)) {
|
||||
@ -577,7 +588,8 @@ static int tpm_cr50_i2c_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
|
||||
* that is inserted by tpm_cr50_i2c_write()
|
||||
*/
|
||||
limit = min_t(size_t, burstcnt - 1, len);
|
||||
rc = tpm_cr50_i2c_write(chip, TPM_I2C_DATA_FIFO(0), &buf[sent], limit);
|
||||
rc = tpm_cr50_i2c_write(chip, TPM_I2C_DATA_FIFO(chip->locality),
|
||||
&buf[sent], limit);
|
||||
if (rc < 0) {
|
||||
dev_err(&chip->dev, "Write failed\n");
|
||||
goto out_err;
|
||||
@ -598,7 +610,7 @@ static int tpm_cr50_i2c_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
|
||||
}
|
||||
|
||||
/* Start the TPM command */
|
||||
rc = tpm_cr50_i2c_write(chip, TPM_I2C_STS(0), tpm_go,
|
||||
rc = tpm_cr50_i2c_write(chip, TPM_I2C_STS(chip->locality), tpm_go,
|
||||
sizeof(tpm_go));
|
||||
if (rc < 0) {
|
||||
dev_err(&chip->dev, "Start command failed\n");
|
||||
@ -611,7 +623,6 @@ out_err:
|
||||
if (tpm_cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY)
|
||||
tpm_cr50_i2c_tis_set_ready(chip);
|
||||
|
||||
tpm_cr50_release_locality(chip, false);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -650,6 +661,8 @@ static const struct tpm_class_ops cr50_i2c = {
|
||||
.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||
.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
|
||||
.req_canceled = &tpm_cr50_i2c_req_canceled,
|
||||
.request_locality = &tpm_cr50_request_locality,
|
||||
.relinquish_locality = &tpm_cr50_release_locality,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
@ -668,6 +681,27 @@ static const struct of_device_id of_cr50_i2c_match[] = {
|
||||
MODULE_DEVICE_TABLE(of, of_cr50_i2c_match);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* tpm_cr50_vid_to_name() - Maps VID to name.
|
||||
* @vendor: Vendor identifier to map to name
|
||||
*
|
||||
* Return:
|
||||
* A valid string for the vendor or empty string
|
||||
*/
|
||||
static const char *tpm_cr50_vid_to_name(u32 vendor)
|
||||
{
|
||||
switch (vendor) {
|
||||
case TPM_CR50_I2C_DID_VID:
|
||||
return "cr50";
|
||||
case TPM_TI50_DT_I2C_DID_VID:
|
||||
return "ti50 DT";
|
||||
case TPM_TI50_OT_I2C_DID_VID:
|
||||
return "ti50 OT";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* tpm_cr50_i2c_probe() - Driver probe function.
|
||||
* @client: I2C client information.
|
||||
@ -684,6 +718,7 @@ static int tpm_cr50_i2c_probe(struct i2c_client *client)
|
||||
u32 vendor;
|
||||
u8 buf[4];
|
||||
int rc;
|
||||
int loc;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
|
||||
return -ENODEV;
|
||||
@ -726,29 +761,37 @@ static int tpm_cr50_i2c_probe(struct i2c_client *client)
|
||||
TPM_CR50_TIMEOUT_NOIRQ_MS);
|
||||
}
|
||||
|
||||
rc = tpm_cr50_request_locality(chip);
|
||||
if (rc < 0) {
|
||||
loc = tpm_cr50_request_locality(chip, TPM_CR50_I2C_DEFAULT_LOC);
|
||||
if (loc < 0) {
|
||||
dev_err(dev, "Could not request locality\n");
|
||||
return rc;
|
||||
return loc;
|
||||
}
|
||||
|
||||
/* Read four bytes from DID_VID register */
|
||||
rc = tpm_cr50_i2c_read(chip, TPM_I2C_DID_VID(0), buf, sizeof(buf));
|
||||
rc = tpm_cr50_i2c_read(chip, TPM_I2C_DID_VID(loc), buf, sizeof(buf));
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "Could not read vendor id\n");
|
||||
tpm_cr50_release_locality(chip, true);
|
||||
if (tpm_cr50_release_locality(chip, loc))
|
||||
dev_err(dev, "Could not release locality\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = tpm_cr50_release_locality(chip, loc);
|
||||
if (rc) {
|
||||
dev_err(dev, "Could not release locality\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
vendor = le32_to_cpup((__le32 *)buf);
|
||||
if (vendor != TPM_CR50_I2C_DID_VID && vendor != TPM_TI50_I2C_DID_VID) {
|
||||
if (vendor != TPM_CR50_I2C_DID_VID &&
|
||||
vendor != TPM_TI50_DT_I2C_DID_VID &&
|
||||
vendor != TPM_TI50_OT_I2C_DID_VID) {
|
||||
dev_err(dev, "Vendor ID did not match! ID was %08x\n", vendor);
|
||||
tpm_cr50_release_locality(chip, true);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev_info(dev, "%s TPM 2.0 (i2c 0x%02x irq %d id 0x%x)\n",
|
||||
vendor == TPM_TI50_I2C_DID_VID ? "ti50" : "cr50",
|
||||
tpm_cr50_vid_to_name(vendor),
|
||||
client->addr, client->irq, vendor >> 16);
|
||||
return tpm_chip_register(chip);
|
||||
}
|
||||
@ -772,7 +815,6 @@ static void tpm_cr50_i2c_remove(struct i2c_client *client)
|
||||
}
|
||||
|
||||
tpm_chip_unregister(chip);
|
||||
tpm_cr50_release_locality(chip, true);
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(cr50_i2c_pm, tpm_pm_suspend, tpm_pm_resume);
|
||||
|
Loading…
Reference in New Issue
Block a user