Add support for i2c devices

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEgWII69YpahbL5iK5gS8AYozs+qIFAmKMeSMACgkQgS8AYozs
 +qKaFBAAobMRGBaodExMxmgdDDeogx5bsAhBIXfB76XJ3JnG2hrJFeUdRWyjCQ3N
 DCmthdC9mjC4GoofJklcB3r6YCsiI6W3VPnh8gPS7xWS5Y+I+HKDgWsm0pcT3HdD
 PPO4bd1mS3F0/XMizjPaFEhwhLWepjiBTFquy+R8gBcItL3l+LNBTKAGmdNNTrWa
 4ouqJPJ2Hu5xB4k42Vm8gtS3Ex8M3qSUnRgwv7speier/6lFEyvsf2/MBZPoPtNh
 DaLv3JkvVDOY+qOO1uHWnlmXfBPcooItTUo2aK7i3dFTBRyhIQgGxMgR/gCKJESc
 PuiRNfsCDcg0JX4gBNVlzWkNuo0T/GvKqHZId/1FLZ+RLeTu4DcMCuy1RO6pxroN
 76ItR3XZpCrUHzgjBI2tDcbRd5L5KAk7AyH4Ag/vEGvJGePSQy4jY72L1iC4oehH
 6e0x5EgkBhE5KimaWF97q85J0B/o7CPptKpqxM2klPr3j78pEzuy7Fl8NIrDTEWW
 agdwJ6IBoR3Cnoo2cRx1WeqJmpiOHwj4COqTRjeB3vEcO+O/TXMSo0qKhuIlbPiP
 yqQTOcnL1q3NotVTs4ot7zJSJfN66x0Q0snV6UaZPPh3Xl1uzBmc8V/6dR50U7tA
 dMmSAjvmpOqPPiAsmDOe8e9suOlx2L7cT2fgUfx1MzT0SelZItA=
 =43CM
 -----END PGP SIGNATURE-----

Merge tag 'tpm-24052022' of https://source.denx.de/u-boot/custodians/u-boot-tpm

Add support for i2c devices
This commit is contained in:
Tom Rini 2022-05-24 09:03:34 -04:00
commit 1b04a961c6
4 changed files with 185 additions and 3 deletions

View file

@ -185,6 +185,15 @@ config TPM2_TIS_SPI
to the device using the standard TPM Interface Specification (TIS)
protocol.
config TPM2_TIS_I2C
bool "Enable support for TPMv2.x I2C chips"
depends on TPM_V2 && DM_I2C
help
This driver supports TPMv2.x devices connected on the I2C bus.
The usual TPM operations and the 'tpm' command can be used to talk
to the device using the standard TPM Interface Specification (TIS)
protocol.
config TPM2_FTPM_TEE
bool "TEE based fTPM Interface"
depends on TEE && OPTEE && TPM_V2

View file

@ -13,5 +13,6 @@ obj-$(CONFIG_TPM_ST33ZP24_SPI) += tpm_tis_st33zp24_spi.o
obj-$(CONFIG_$(SPL_TPL_)TPM2_CR50_I2C) += cr50_i2c.o
obj-$(CONFIG_TPM2_TIS_SANDBOX) += tpm2_tis_sandbox.o sandbox_common.o
obj-$(CONFIG_TPM2_TIS_SPI) += tpm2_tis_core.o tpm2_tis_spi.o
obj-$(CONFIG_TPM2_TIS_I2C) += tpm2_tis_core.o tpm2_tis_i2c.o
obj-$(CONFIG_TPM2_FTPM_TEE) += tpm2_ftpm_tee.o
obj-$(CONFIG_TPM2_MMIO) += tpm2_tis_core.o tpm2_tis_mmio.o

View file

@ -433,15 +433,16 @@ int tpm_tis_init(struct udevice *dev)
log_err("Driver bug. No bus ops defined\n");
return -1;
}
ret = tpm_tis_request_locality(dev, 0);
if (ret)
return ret;
chip->timeout_a = TIS_SHORT_TIMEOUT_MS;
chip->timeout_b = TIS_LONG_TIMEOUT_MS;
chip->timeout_c = TIS_SHORT_TIMEOUT_MS;
chip->timeout_d = TIS_SHORT_TIMEOUT_MS;
ret = tpm_tis_request_locality(dev, 0);
if (ret)
return ret;
/* Disable interrupts */
phy_ops->read32(dev, TPM_INT_ENABLE(chip->locality), &tmp);
tmp |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |

171
drivers/tpm/tpm2_tis_i2c.c Normal file
View file

@ -0,0 +1,171 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2022 IBM Corp.
*/
#include <common.h>
#include <dm.h>
#include <fdtdec.h>
#include <i2c.h>
#include <log.h>
#include <tpm-v2.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/compiler.h>
#include <linux/types.h>
#include <linux/unaligned/be_byteshift.h>
#include <asm-generic/gpio.h>
#include "tpm_tis.h"
#include "tpm_internal.h"
struct tpm_tis_chip_data {
unsigned int pcr_count;
unsigned int pcr_select_min;
};
static uint tpm_tis_i2c_address_to_register(u32 addr)
{
addr &= 0xFFF;
/*
* Adapt register addresses that have changed compared to older TIS
* version.
*/
switch (addr) {
case TPM_ACCESS(0):
return 0x04;
case TPM_DID_VID(0):
return 0x48;
case TPM_RID(0):
return 0x4C;
default:
return addr;
}
}
static int tpm_tis_i2c_read(struct udevice *dev, u32 addr, u16 len, u8 *in)
{
int rc;
int count = 0;
uint reg = tpm_tis_i2c_address_to_register(addr);
do {
rc = dm_i2c_read(dev, reg, in, len);
udelay(SLEEP_DURATION_US);
} while (rc && count++ < MAX_COUNT);
return rc;
}
static int tpm_tis_i2c_write(struct udevice *dev, u32 addr, u16 len,
const u8 *out)
{
int rc;
int count = 0;
uint reg = tpm_tis_i2c_address_to_register(addr);
do {
rc = dm_i2c_write(dev, reg, out, len);
udelay(SLEEP_DURATION_US);
} while (rc && count++ < MAX_COUNT);
return rc;
}
static int tpm_tis_i2c_read32(struct udevice *dev, u32 addr, u32 *result)
{
__le32 result_le;
int rc;
rc = tpm_tis_i2c_read(dev, addr, sizeof(u32), (u8 *)&result_le);
if (!rc)
*result = le32_to_cpu(result_le);
return rc;
}
static int tpm_tis_i2c_write32(struct udevice *dev, u32 addr, u32 value)
{
__le32 value_le = cpu_to_le32(value);
return tpm_tis_i2c_write(dev, addr, sizeof(value), (u8 *)&value_le);
}
static struct tpm_tis_phy_ops phy_ops = {
.read_bytes = tpm_tis_i2c_read,
.write_bytes = tpm_tis_i2c_write,
.read32 = tpm_tis_i2c_read32,
.write32 = tpm_tis_i2c_write32,
};
static int tpm_tis_i2c_probe(struct udevice *udev)
{
struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(udev);
struct tpm_chip_priv *priv = dev_get_uclass_priv(udev);
int rc;
u8 loc = 0;
tpm_tis_ops_register(udev, &phy_ops);
/*
* Force locality 0. The core driver doesn't actually write the
* locality register and instead just reads/writes various access
* bits of the selected locality.
*/
rc = dm_i2c_write(udev, 0, &loc, 1);
if (rc)
return rc;
rc = tpm_tis_init(udev);
if (rc)
return rc;
priv->pcr_count = drv_data->pcr_count;
priv->pcr_select_min = drv_data->pcr_select_min;
priv->version = TPM_V2;
return 0;
}
static int tpm_tis_i2c_remove(struct udevice *udev)
{
return tpm_tis_cleanup(udev);
}
static const struct tpm_ops tpm_tis_i2c_ops = {
.open = tpm_tis_open,
.close = tpm_tis_close,
.get_desc = tpm_tis_get_desc,
.send = tpm_tis_send,
.recv = tpm_tis_recv,
.cleanup = tpm_tis_cleanup,
};
static const struct tpm_tis_chip_data tpm_tis_std_chip_data = {
.pcr_count = 24,
.pcr_select_min = 3,
};
static const struct udevice_id tpm_tis_i2c_ids[] = {
{
.compatible = "nuvoton,npct75x",
.data = (ulong)&tpm_tis_std_chip_data,
},
{
.compatible = "tcg,tpm-tis-i2c",
.data = (ulong)&tpm_tis_std_chip_data,
},
{ }
};
U_BOOT_DRIVER(tpm_tis_i2c) = {
.name = "tpm_tis_i2c",
.id = UCLASS_TPM,
.of_match = tpm_tis_i2c_ids,
.ops = &tpm_tis_i2c_ops,
.probe = tpm_tis_i2c_probe,
.remove = tpm_tis_i2c_remove,
.priv_auto = sizeof(struct tpm_chip),
};