tpm_i2c_nuvoton: Use struct of constants instead of macros
This driver was originally developed with only the npct650 chip in mind,
which was developed before there was a TCG standard for a TPM on the i2c
bus. Therefore, many constants were hardcoded using macros for the
specific expected offsets and vendor information for this particular
chip.
To allow support for other potential Nuvoton (or maybe other i2c) chips,
this patch factors out the constants into a struct so that other chips
may be added, and the correct set of constants can be selected at
runtime.
Signed-off-by: Eric Richter <erichte@linux.ibm.com>
Signed-off-by: Reza Arbab <arbab@linux.ibm.com>
diff --git a/libstb/drivers/tpm_i2c_nuvoton.c b/libstb/drivers/tpm_i2c_nuvoton.c
index 0aa9711..e7cb477 100644
--- a/libstb/drivers/tpm_i2c_nuvoton.c
+++ b/libstb/drivers/tpm_i2c_nuvoton.c
@@ -16,13 +16,6 @@
#define DRIVER_NAME "i2c_tpm_nuvoton"
-/* I2C interface offsets */
-#define TPM_STS 0x00
-#define TPM_BURST_COUNT 0x01
-#define TPM_DATA_FIFO_W 0x20
-#define TPM_DATA_FIFO_R 0x40
-#define TPM_VID_DID 0x60
-
/* Bit masks for the TPM STATUS register */
#define TPM_STS_VALID 0x80
#define TPM_STS_COMMAND_READY 0x40
@@ -34,15 +27,35 @@
/* TPM Driver values */
#define MAX_STSVALID_POLLS 5
#define TPM_TIMEOUT_INTERVAL 10
-#define TPM_NUVOTON_VID 0x5010FE00
#define TPM_VENDOR_ID_MASK 0xFFFFFF00
+struct tpm_info {
+ const char *compatible;
+ uint32_t vendor_id;
+ uint8_t sts;
+ uint8_t burst_count;
+ uint8_t data_fifo_w;
+ uint8_t data_fifo_r;
+ uint8_t vid_did;
+};
+
+static const struct tpm_info tpm_nuvoton_650 = {
+ .compatible = "nuvoton,npct650",
+ .vendor_id = 0x5010FE00,
+ .sts = 0x00,
+ .burst_count = 0x01,
+ .data_fifo_w = 0x20,
+ .data_fifo_r = 0x40,
+ .vid_did = 0x60,
+};
+
static struct tpm_dev *tpm_device = NULL;
+static const struct tpm_info *tpm_info = NULL;
static int tpm_status_write_byte(uint8_t byte)
{
uint8_t value = byte;
- return tpm_i2c_request_send(tpm_device, SMBUS_WRITE, TPM_STS, 1, &value,
+ return tpm_i2c_request_send(tpm_device, SMBUS_WRITE, tpm_info->sts, 1, &value,
sizeof(value));
}
@@ -68,7 +81,7 @@
do {
now = mftb();
- rc = tpm_status_read_byte(TPM_STS, &status);
+ rc = tpm_status_read_byte(tpm_info->sts, &status);
if (rc < 0) {
/**
* @fwts-label TPMReadCmdReady
@@ -138,7 +151,7 @@
uint8_t status;
for(retries = 0; retries <= MAX_STSVALID_POLLS; retries++) {
- rc = tpm_status_read_byte(TPM_STS, &status);
+ rc = tpm_status_read_byte(tpm_info->sts, &status);
if (rc < 0) {
/**
* @fwts-label TPMReadFifoStatus
@@ -170,7 +183,7 @@
do {
now = mftb();
- rc = tpm_status_read_byte(TPM_STS, &status);
+ rc = tpm_status_read_byte(tpm_info->sts, &status);
if (rc < 0) {
/**
* @fwts-label TPMReadDataAvail
@@ -218,7 +231,7 @@
do {
now = mftb();
/* In i2C, burstCount is 1 byte */
- rc = tpm_status_read_byte(TPM_BURST_COUNT, &burst_count);
+ rc = tpm_status_read_byte(tpm_info->burst_count, &burst_count);
if (rc == 0 && burst_count > 0) {
DBG("---- burst_count=%d, delay=%lu/%d\n", burst_count,
tb_to_msecs(now-start), TPM_TIMEOUT_D);
@@ -272,7 +285,7 @@
(buflen - 1 - count) : burst_count);
rc = tpm_i2c_request_send(tpm_device,
- SMBUS_WRITE, TPM_DATA_FIFO_W,
+ SMBUS_WRITE, tpm_info->data_fifo_w,
1, &buf[count], bytes);
count += bytes;
DBG("%s FIFO: %zd bytes written, count=%zd, rc=%d\n",
@@ -315,7 +328,7 @@
rc = tpm_i2c_request_send(tpm_device,
SMBUS_WRITE,
- TPM_DATA_FIFO_W, 1,
+ tpm_info->data_fifo_w, 1,
&buf[count], 1);
count++;
DBG("%s FIFO: last byte written, count=%zd, rc=%d\n",
@@ -381,7 +394,7 @@
}
rc = tpm_i2c_request_send(tpm_device,
SMBUS_READ,
- TPM_DATA_FIFO_R, 1,
+ tpm_info->data_fifo_r, 1,
&buf[count], burst_count);
count += burst_count;
DBG("%s FIFO: %d bytes read, count=%zd, rc=%d\n",
@@ -541,7 +554,7 @@
return 0;
}
-void tpm_i2c_nuvoton_probe(void)
+static void __tpm_i2c_nuvoton_probe(const struct tpm_info *info)
{
struct tpm_dev *tpm_device = NULL;
struct dt_node *node = NULL;
@@ -549,9 +562,10 @@
const char *name;
uint32_t vendor = 0;
- dt_for_each_compatible(dt_root, node, "nuvoton,npct650") {
+ dt_for_each_compatible(dt_root, node, info->compatible) {
if (!dt_node_is_enabled(node))
continue;
+ tpm_info = info;
tpm_device = (struct tpm_dev*) malloc(sizeof(struct tpm_dev));
assert(tpm_device);
/*
@@ -585,12 +599,12 @@
goto disable;
}
/* ensure there's really the TPM we expect at that address */
- if (tpm_i2c_request_send(tpm_device, SMBUS_READ, TPM_VID_DID,
+ if (tpm_i2c_request_send(tpm_device, SMBUS_READ, tpm_info->vid_did,
1, &vendor, sizeof(vendor))) {
prlog(PR_ERR, "NUVOTON: i2c device inaccessible\n");
goto disable;
}
- if ((vendor & TPM_VENDOR_ID_MASK) != TPM_NUVOTON_VID) {
+ if ((vendor & TPM_VENDOR_ID_MASK) != tpm_info->vendor_id) {
prlog(PR_ERR, "NUVOTON: expected vendor id mismatch\n");
goto disable;
}
@@ -625,3 +639,8 @@
prlog(PR_NOTICE, "TPM: tpm node %p disabled\n", node);
free(tpm_device);
}
+
+void tpm_i2c_nuvoton_probe(void)
+{
+ __tpm_i2c_nuvoton_probe(&tpm_nuvoton_650);
+}