X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-uboot.git;a=blobdiff_plain;f=drivers%2Ftpm%2Ftpm_tis_i2c.c;h=438a22160747ee4414384a5d404b0a2223c4ad34;hp=2dd8501f92d127125dec36d09f9af25a2ecac87b;hb=0bfcc924552b8ec79a20b8b12557ff08742c4f0e;hpb=f0df254663d44f7fd4b714542bb4602626837465 diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_i2c.c index 2dd8501f92..438a221607 100644 --- a/drivers/tpm/tpm_tis_i2c.c +++ b/drivers/tpm/tpm_tis_i2c.c @@ -17,28 +17,13 @@ * * Version: 2.1.1 * - * See file CREDITS for list of people who contributed to this - * project. - * - * 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 the Free Software Foundation, version 2 of the - * License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0 */ #include +#include #include -#include +#include #include #include #include @@ -49,9 +34,6 @@ DECLARE_GLOBAL_DATA_PTR; -/* Address of the TPM on the I2C bus */ -#define TPM_I2C_ADDR 0x20 - /* Max buffer size supported by our tpm */ #define TPM_DEV_BUFSIZE 1260 @@ -72,13 +54,6 @@ DECLARE_GLOBAL_DATA_PTR; #define TPM_HEADER_SIZE 10 -/* - * Expected value for DIDVID register - * - * The only device the system knows about at this moment is Infineon slb9635. - */ -#define TPM_TIS_I2C_DID_VID 0x000b15d1L - enum tis_access { TPM_ACCESS_VALID = 0x80, TPM_ACCESS_ACTIVE_LOCALITY = 0x20, @@ -122,15 +97,11 @@ static const char * const chip_name[] = { /* Structure to store I2C TPM specific stuff */ struct tpm_dev { - uint addr; + struct udevice *dev; u8 buf[TPM_DEV_BUFSIZE + sizeof(u8)]; /* Max buffer size + addr */ enum i2c_chip_type chip_type; }; -static struct tpm_dev tpm_dev = { - .addr = TPM_I2C_ADDR -}; - static struct tpm_dev tpm_dev; /* @@ -156,8 +127,7 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) if ((tpm_dev.chip_type == SLB9635) || (tpm_dev.chip_type == UNKNOWN)) { /* slb9635 protocol should work in both cases */ for (count = 0; count < MAX_COUNT; count++) { - rc = i2c_write(tpm_dev.addr, 0, 0, - (uchar *)&addrbuf, 1); + rc = dm_i2c_write(tpm_dev.dev, 0, (uchar *)&addrbuf, 1); if (rc == 0) break; /* Success, break to skip sleep */ udelay(SLEEP_DURATION); @@ -171,7 +141,7 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) */ for (count = 0; count < MAX_COUNT; count++) { udelay(SLEEP_DURATION); - rc = i2c_read(tpm_dev.addr, 0, 0, buffer, len); + rc = dm_i2c_read(tpm_dev.dev, 0, buffer, len); if (rc == 0) break; /* success, break to skip sleep */ } @@ -184,7 +154,7 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) * be safe on the safe side. */ for (count = 0; count < MAX_COUNT; count++) { - rc = i2c_read(tpm_dev.addr, addr, 1, buffer, len); + rc = dm_i2c_read(tpm_dev.dev, addr, buffer, len); if (rc == 0) break; /* break here to skip sleep */ udelay(SLEEP_DURATION); @@ -205,19 +175,15 @@ static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, int rc = 0; int count; - /* Prepare send buffer */ - tpm_dev.buf[0] = addr; - memcpy(&(tpm_dev.buf[1]), buffer, len); - for (count = 0; count < max_count; count++) { - rc = i2c_write(tpm_dev.addr, 0, 0, tpm_dev.buf, len + 1); + rc = dm_i2c_write(tpm_dev.dev, addr, buffer, len); if (rc == 0) break; /* Success, break to skip sleep */ udelay(sleep_time); } /* take care of 'guard time' */ - udelay(SLEEP_DURATION); + udelay(sleep_time); if (rc) return -rc; @@ -292,11 +258,14 @@ static int request_locality(struct tpm_chip *chip, int loc) { unsigned long start, stop; u8 buf = TPM_ACCESS_REQUEST_USE; + int rc; if (check_locality(chip, loc) >= 0) return loc; /* We already have the locality */ - iic_tpm_write(TPM_ACCESS(loc), &buf, 1); + rc = iic_tpm_write(TPM_ACCESS(loc), &buf, 1); + if (rc) + return rc; /* Wait for burstcount */ start = get_timer(0); @@ -323,10 +292,15 @@ static u8 tpm_tis_i2c_status(struct tpm_chip *chip) static void tpm_tis_i2c_ready(struct tpm_chip *chip) { + int rc; + /* This causes the current command to be aborted */ u8 buf = TPM_STS_COMMAND_READY; - iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1); + debug("%s\n", __func__); + rc = iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1); + if (rc) + debug("%s: rc=%d\n", __func__, rc); } static ssize_t get_burstcount(struct tpm_chip *chip) @@ -422,6 +396,8 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) expected = get_unaligned_be32(buf + TPM_RSP_SIZE_BYTE); if ((size_t)expected > count) { + error("Error size=%x, expected=%x, count=%x\n", size, expected, + count); size = -EIO; goto out; } @@ -456,11 +432,12 @@ out: static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) { int rc, status; - ssize_t burstcnt; + size_t burstcnt; size_t count = 0; int retry = 0; u8 sts = TPM_STS_GO; + debug("%s: len=%d\n", __func__, len); if (len > TPM_DEV_BUFSIZE) return -E2BIG; /* Command is too long for our tpm, sorry */ @@ -483,9 +460,10 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) if (burstcnt < 0) return burstcnt; - while (count < len - 1) { - if (burstcnt > len - 1 - count) - burstcnt = len - 1 - count; + while (count < len) { + udelay(300); + if (burstcnt > len - count) + burstcnt = len - count; #ifdef CONFIG_TPM_TIS_I2C_BURST_LIMITATION if (retry && burstcnt > CONFIG_TPM_TIS_I2C_BURST_LIMITATION) @@ -497,9 +475,15 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) if (rc == 0) count += burstcnt; else { - retry++; - wait_for_stat(chip, TPM_STS_VALID, - chip->vendor.timeout_c, &status); + debug("%s: error\n", __func__); + if (retry++ > 10) { + rc = -EIO; + goto out_err; + } + rc = wait_for_stat(chip, TPM_STS_VALID, + chip->vendor.timeout_c, &status); + if (rc) + goto out_err; if ((status & TPM_STS_DATA_EXPECT) == 0) { rc = -EIO; @@ -508,20 +492,14 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) } } - /* Write last byte */ - iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1); - wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); - if ((status & TPM_STS_DATA_EXPECT) != 0) { - rc = -EIO; - goto out_err; - } - /* Go and do it */ iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1); + debug("done\n"); return len; out_err: + debug("%s: out_err\n", __func__); tpm_tis_i2c_ready(chip); /* * The TPM needs some time to clean up here, @@ -546,7 +524,7 @@ static struct tpm_vendor_specific tpm_tis_i2c = { static enum i2c_chip_type tpm_vendor_chip_type(void) { -#ifdef CONFIG_OF_CONTROL +#if CONFIG_IS_ENABLED(OF_CONTROL) const void *blob = gd->fdt_blob; if (fdtdec_next_compatible(blob, 0, COMPAT_INFINEON_SLB9645_TPM) >= 0) @@ -558,26 +536,18 @@ static enum i2c_chip_type tpm_vendor_chip_type(void) return UNKNOWN; } -/* Initialisation of i2c tpm */ -int tpm_vendor_init(uint32_t dev_addr) +int tpm_vendor_init(struct udevice *dev) { + struct tpm_chip *chip; u32 vendor; u32 expected_did_vid; - uint old_addr; - int rc = 0; - struct tpm_chip *chip; - - old_addr = tpm_dev.addr; - if (dev_addr != 0) - tpm_dev.addr = dev_addr; + tpm_dev.dev = dev; tpm_dev.chip_type = tpm_vendor_chip_type(); chip = tpm_register_hardware(&tpm_tis_i2c); - if (chip < 0) { - rc = -ENODEV; - goto out_err; - } + if (chip < 0) + return -ENODEV; /* Disable interrupts (not supported) */ chip->vendor.irq = 0; @@ -588,15 +558,13 @@ int tpm_vendor_init(uint32_t dev_addr) chip->vendor.timeout_c = TIS_SHORT_TIMEOUT; chip->vendor.timeout_d = TIS_SHORT_TIMEOUT; - if (request_locality(chip, 0) < 0) { - rc = -ENODEV; - goto out_err; - } + if (request_locality(chip, 0) < 0) + return -ENODEV; /* Read four bytes from DID_VID register */ if (iic_tpm_read(TPM_DID_VID(0), (uchar *)&vendor, 4) < 0) { - rc = -EIO; - goto out_release; + release_locality(chip, 0, 1); + return -EIO; } if (tpm_dev.chip_type == SLB9635) { @@ -609,8 +577,7 @@ int tpm_vendor_init(uint32_t dev_addr) if (tpm_dev.chip_type != UNKNOWN && vendor != expected_did_vid) { error("Vendor id did not match! ID was %08x\n", vendor); - rc = -ENODEV; - goto out_release; + return -ENODEV; } debug("1.2 TPM (chip type %s device-id 0x%X)\n", @@ -622,13 +589,6 @@ int tpm_vendor_init(uint32_t dev_addr) */ return 0; - -out_release: - release_locality(chip, 0, 1); - -out_err: - tpm_dev.addr = old_addr; - return rc; } void tpm_vendor_cleanup(struct tpm_chip *chip)