10766ad2fSChristophe Ricard /*
20766ad2fSChristophe Ricard * Copyright (C) 2011 Infineon Technologies
30766ad2fSChristophe Ricard *
40766ad2fSChristophe Ricard * Authors:
50766ad2fSChristophe Ricard * Peter Huewe <huewe.external@infineon.com>
60766ad2fSChristophe Ricard *
70766ad2fSChristophe Ricard * Description:
80766ad2fSChristophe Ricard * Device driver for TCG/TCPA TPM (trusted platform module).
90766ad2fSChristophe Ricard * Specifications at www.trustedcomputinggroup.org
100766ad2fSChristophe Ricard *
110766ad2fSChristophe Ricard * This device driver implements the TPM interface as defined in
120766ad2fSChristophe Ricard * the TCG TPM Interface Spec version 1.2, revision 1.0 and the
130766ad2fSChristophe Ricard * Infineon I2C Protocol Stack Specification v0.20.
140766ad2fSChristophe Ricard *
150766ad2fSChristophe Ricard * It is based on the Linux kernel driver tpm.c from Leendert van
160766ad2fSChristophe Ricard * Dorn, Dave Safford, Reiner Sailer, and Kyleen Hall.
170766ad2fSChristophe Ricard *
180766ad2fSChristophe Ricard * Version: 2.1.1
190766ad2fSChristophe Ricard *
200766ad2fSChristophe Ricard * SPDX-License-Identifier: GPL-2.0
210766ad2fSChristophe Ricard */
220766ad2fSChristophe Ricard
230766ad2fSChristophe Ricard #include <common.h>
240766ad2fSChristophe Ricard #include <dm.h>
250766ad2fSChristophe Ricard #include <fdtdec.h>
260766ad2fSChristophe Ricard #include <i2c.h>
270766ad2fSChristophe Ricard #include <tpm.h>
285d97dff0SMasahiro Yamada #include <linux/errno.h>
290766ad2fSChristophe Ricard #include <linux/compiler.h>
300766ad2fSChristophe Ricard #include <linux/types.h>
310766ad2fSChristophe Ricard #include <linux/unaligned/be_byteshift.h>
320766ad2fSChristophe Ricard
331259dcd7SChristophe Ricard #include "tpm_tis.h"
340766ad2fSChristophe Ricard #include "tpm_internal.h"
350766ad2fSChristophe Ricard
360766ad2fSChristophe Ricard DECLARE_GLOBAL_DATA_PTR;
370766ad2fSChristophe Ricard
381259dcd7SChristophe Ricard enum i2c_chip_type {
391259dcd7SChristophe Ricard SLB9635,
401259dcd7SChristophe Ricard SLB9645,
411259dcd7SChristophe Ricard UNKNOWN,
421259dcd7SChristophe Ricard };
431259dcd7SChristophe Ricard
441259dcd7SChristophe Ricard /* expected value for DIDVID register */
451259dcd7SChristophe Ricard #define TPM_TIS_I2C_DID_VID_9635 0x000b15d1L
461259dcd7SChristophe Ricard #define TPM_TIS_I2C_DID_VID_9645 0x001a15d1L
471259dcd7SChristophe Ricard
480766ad2fSChristophe Ricard static const char * const chip_name[] = {
490766ad2fSChristophe Ricard [SLB9635] = "slb9635tt",
500766ad2fSChristophe Ricard [SLB9645] = "slb9645tt",
510766ad2fSChristophe Ricard [UNKNOWN] = "unknown/fallback to slb9635",
520766ad2fSChristophe Ricard };
530766ad2fSChristophe Ricard
541259dcd7SChristophe Ricard #define TPM_ACCESS(l) (0x0000 | ((l) << 4))
551259dcd7SChristophe Ricard #define TPM_STS(l) (0x0001 | ((l) << 4))
561259dcd7SChristophe Ricard #define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4))
571259dcd7SChristophe Ricard #define TPM_DID_VID(l) (0x0006 | ((l) << 4))
581259dcd7SChristophe Ricard
590766ad2fSChristophe Ricard /*
600766ad2fSChristophe Ricard * tpm_tis_i2c_read() - read from TPM register
610766ad2fSChristophe Ricard * @addr: register address to read from
620766ad2fSChristophe Ricard * @buffer: provided by caller
630766ad2fSChristophe Ricard * @len: number of bytes to read
640766ad2fSChristophe Ricard *
650766ad2fSChristophe Ricard * Read len bytes from TPM register and put them into
660766ad2fSChristophe Ricard * buffer (little-endian format, i.e. first byte is put into buffer[0]).
670766ad2fSChristophe Ricard *
680766ad2fSChristophe Ricard * NOTE: TPM is big-endian for multi-byte values. Multi-byte
690766ad2fSChristophe Ricard * values have to be swapped.
700766ad2fSChristophe Ricard *
710766ad2fSChristophe Ricard * Return -EIO on error, 0 on success.
720766ad2fSChristophe Ricard */
tpm_tis_i2c_read(struct udevice * dev,u8 addr,u8 * buffer,size_t len)730766ad2fSChristophe Ricard static int tpm_tis_i2c_read(struct udevice *dev, u8 addr, u8 *buffer,
740766ad2fSChristophe Ricard size_t len)
750766ad2fSChristophe Ricard {
760766ad2fSChristophe Ricard struct tpm_chip *chip = dev_get_priv(dev);
770766ad2fSChristophe Ricard int rc;
780766ad2fSChristophe Ricard int count;
790766ad2fSChristophe Ricard uint32_t addrbuf = addr;
800766ad2fSChristophe Ricard
810766ad2fSChristophe Ricard if ((chip->chip_type == SLB9635) || (chip->chip_type == UNKNOWN)) {
820766ad2fSChristophe Ricard /* slb9635 protocol should work in both cases */
830766ad2fSChristophe Ricard for (count = 0; count < MAX_COUNT; count++) {
840766ad2fSChristophe Ricard rc = dm_i2c_write(dev, 0, (uchar *)&addrbuf, 1);
850766ad2fSChristophe Ricard if (rc == 0)
860766ad2fSChristophe Ricard break; /* Success, break to skip sleep */
870766ad2fSChristophe Ricard udelay(SLEEP_DURATION_US);
880766ad2fSChristophe Ricard }
890766ad2fSChristophe Ricard if (rc)
900766ad2fSChristophe Ricard return rc;
910766ad2fSChristophe Ricard
920766ad2fSChristophe Ricard /* After the TPM has successfully received the register address
930766ad2fSChristophe Ricard * it needs some time, thus we're sleeping here again, before
940766ad2fSChristophe Ricard * retrieving the data
950766ad2fSChristophe Ricard */
960766ad2fSChristophe Ricard for (count = 0; count < MAX_COUNT; count++) {
970766ad2fSChristophe Ricard udelay(SLEEP_DURATION_US);
980766ad2fSChristophe Ricard rc = dm_i2c_read(dev, 0, buffer, len);
990766ad2fSChristophe Ricard if (rc == 0)
1000766ad2fSChristophe Ricard break; /* success, break to skip sleep */
1010766ad2fSChristophe Ricard }
1020766ad2fSChristophe Ricard } else {
1030766ad2fSChristophe Ricard /*
1040766ad2fSChristophe Ricard * Use a combined read for newer chips.
1050766ad2fSChristophe Ricard * Unfortunately the smbus functions are not suitable due to
1060766ad2fSChristophe Ricard * the 32 byte limit of the smbus.
1070766ad2fSChristophe Ricard * Retries should usually not be needed, but are kept just to
1080766ad2fSChristophe Ricard * be safe on the safe side.
1090766ad2fSChristophe Ricard */
1100766ad2fSChristophe Ricard for (count = 0; count < MAX_COUNT; count++) {
1110766ad2fSChristophe Ricard rc = dm_i2c_read(dev, addr, buffer, len);
1120766ad2fSChristophe Ricard if (rc == 0)
1130766ad2fSChristophe Ricard break; /* break here to skip sleep */
1140766ad2fSChristophe Ricard udelay(SLEEP_DURATION_US);
1150766ad2fSChristophe Ricard }
1160766ad2fSChristophe Ricard }
1170766ad2fSChristophe Ricard
1180766ad2fSChristophe Ricard /* Take care of 'guard time' */
1190766ad2fSChristophe Ricard udelay(SLEEP_DURATION_US);
1200766ad2fSChristophe Ricard if (rc)
1210766ad2fSChristophe Ricard return rc;
1220766ad2fSChristophe Ricard
1230766ad2fSChristophe Ricard return 0;
1240766ad2fSChristophe Ricard }
1250766ad2fSChristophe Ricard
tpm_tis_i2c_write_generic(struct udevice * dev,u8 addr,const u8 * buffer,size_t len,unsigned int sleep_time_us,u8 max_count)1260766ad2fSChristophe Ricard static int tpm_tis_i2c_write_generic(struct udevice *dev, u8 addr,
1270766ad2fSChristophe Ricard const u8 *buffer, size_t len,
1280766ad2fSChristophe Ricard unsigned int sleep_time_us, u8 max_count)
1290766ad2fSChristophe Ricard {
1300766ad2fSChristophe Ricard struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
1310766ad2fSChristophe Ricard struct tpm_chip *chip = dev_get_priv(dev);
1320766ad2fSChristophe Ricard int rc = 0;
1330766ad2fSChristophe Ricard int count;
1340766ad2fSChristophe Ricard
1350766ad2fSChristophe Ricard if (chip->chip_type == SLB9635) {
1360766ad2fSChristophe Ricard /* Prepare send buffer to include the address */
1370766ad2fSChristophe Ricard priv->buf[0] = addr;
1380766ad2fSChristophe Ricard memcpy(&(priv->buf[1]), buffer, len);
1390766ad2fSChristophe Ricard buffer = priv->buf;
1400766ad2fSChristophe Ricard len++;
1410766ad2fSChristophe Ricard addr = 0;
1420766ad2fSChristophe Ricard }
1430766ad2fSChristophe Ricard
1440766ad2fSChristophe Ricard for (count = 0; count < max_count; count++) {
1450766ad2fSChristophe Ricard rc = dm_i2c_write(dev, addr, buffer, len);
1460766ad2fSChristophe Ricard if (rc == 0)
1470766ad2fSChristophe Ricard break; /* Success, break to skip sleep */
1480766ad2fSChristophe Ricard udelay(sleep_time_us);
1490766ad2fSChristophe Ricard }
1500766ad2fSChristophe Ricard
1510766ad2fSChristophe Ricard /* take care of 'guard time' */
1520766ad2fSChristophe Ricard udelay(sleep_time_us);
1530766ad2fSChristophe Ricard if (rc)
1540766ad2fSChristophe Ricard return rc;
1550766ad2fSChristophe Ricard
1560766ad2fSChristophe Ricard return 0;
1570766ad2fSChristophe Ricard }
1580766ad2fSChristophe Ricard
1590766ad2fSChristophe Ricard /*
1600766ad2fSChristophe Ricard * tpm_tis_i2c_write() - write to TPM register
1610766ad2fSChristophe Ricard * @addr: register address to write to
1620766ad2fSChristophe Ricard * @buffer: containing data to be written
1630766ad2fSChristophe Ricard * @len: number of bytes to write
1640766ad2fSChristophe Ricard *
1650766ad2fSChristophe Ricard * Write len bytes from provided buffer to TPM register (little
1660766ad2fSChristophe Ricard * endian format, i.e. buffer[0] is written as first byte).
1670766ad2fSChristophe Ricard *
1680766ad2fSChristophe Ricard * NOTE: TPM is big-endian for multi-byte values. Multi-byte
1690766ad2fSChristophe Ricard * values have to be swapped.
1700766ad2fSChristophe Ricard *
1710766ad2fSChristophe Ricard * NOTE: use this function instead of the tpm_tis_i2c_write_generic function.
1720766ad2fSChristophe Ricard *
1730766ad2fSChristophe Ricard * Return -EIO on error, 0 on success
1740766ad2fSChristophe Ricard */
tpm_tis_i2c_write(struct udevice * dev,u8 addr,const u8 * buffer,size_t len)1750766ad2fSChristophe Ricard static int tpm_tis_i2c_write(struct udevice *dev, u8 addr, const u8 *buffer,
1760766ad2fSChristophe Ricard size_t len)
1770766ad2fSChristophe Ricard {
1780766ad2fSChristophe Ricard return tpm_tis_i2c_write_generic(dev, addr, buffer, len,
1790766ad2fSChristophe Ricard SLEEP_DURATION_US, MAX_COUNT);
1800766ad2fSChristophe Ricard }
1810766ad2fSChristophe Ricard
1820766ad2fSChristophe Ricard /*
1830766ad2fSChristophe Ricard * This function is needed especially for the cleanup situation after
1840766ad2fSChristophe Ricard * sending TPM_READY
1850766ad2fSChristophe Ricard */
tpm_tis_i2c_write_long(struct udevice * dev,u8 addr,u8 * buffer,size_t len)1860766ad2fSChristophe Ricard static int tpm_tis_i2c_write_long(struct udevice *dev, u8 addr, u8 *buffer,
1870766ad2fSChristophe Ricard size_t len)
1880766ad2fSChristophe Ricard {
1890766ad2fSChristophe Ricard return tpm_tis_i2c_write_generic(dev, addr, buffer, len,
1900766ad2fSChristophe Ricard SLEEP_DURATION_LONG_US,
1910766ad2fSChristophe Ricard MAX_COUNT_LONG);
1920766ad2fSChristophe Ricard }
1930766ad2fSChristophe Ricard
tpm_tis_i2c_check_locality(struct udevice * dev,int loc)1940766ad2fSChristophe Ricard static int tpm_tis_i2c_check_locality(struct udevice *dev, int loc)
1950766ad2fSChristophe Ricard {
1960766ad2fSChristophe Ricard const u8 mask = TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID;
1970766ad2fSChristophe Ricard struct tpm_chip *chip = dev_get_priv(dev);
1980766ad2fSChristophe Ricard u8 buf;
1990766ad2fSChristophe Ricard int rc;
2000766ad2fSChristophe Ricard
2010766ad2fSChristophe Ricard rc = tpm_tis_i2c_read(dev, TPM_ACCESS(loc), &buf, 1);
2020766ad2fSChristophe Ricard if (rc < 0)
2030766ad2fSChristophe Ricard return rc;
2040766ad2fSChristophe Ricard
2050766ad2fSChristophe Ricard if ((buf & mask) == mask) {
2060766ad2fSChristophe Ricard chip->locality = loc;
2070766ad2fSChristophe Ricard return loc;
2080766ad2fSChristophe Ricard }
2090766ad2fSChristophe Ricard
2100766ad2fSChristophe Ricard return -ENOENT;
2110766ad2fSChristophe Ricard }
2120766ad2fSChristophe Ricard
tpm_tis_i2c_release_locality(struct udevice * dev,int loc,int force)2130766ad2fSChristophe Ricard static void tpm_tis_i2c_release_locality(struct udevice *dev, int loc,
2140766ad2fSChristophe Ricard int force)
2150766ad2fSChristophe Ricard {
2160766ad2fSChristophe Ricard const u8 mask = TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID;
2170766ad2fSChristophe Ricard u8 buf;
2180766ad2fSChristophe Ricard
2190766ad2fSChristophe Ricard if (tpm_tis_i2c_read(dev, TPM_ACCESS(loc), &buf, 1) < 0)
2200766ad2fSChristophe Ricard return;
2210766ad2fSChristophe Ricard
2220766ad2fSChristophe Ricard if (force || (buf & mask) == mask) {
2230766ad2fSChristophe Ricard buf = TPM_ACCESS_ACTIVE_LOCALITY;
2240766ad2fSChristophe Ricard tpm_tis_i2c_write(dev, TPM_ACCESS(loc), &buf, 1);
2250766ad2fSChristophe Ricard }
2260766ad2fSChristophe Ricard }
2270766ad2fSChristophe Ricard
tpm_tis_i2c_request_locality(struct udevice * dev,int loc)2280766ad2fSChristophe Ricard static int tpm_tis_i2c_request_locality(struct udevice *dev, int loc)
2290766ad2fSChristophe Ricard {
2300766ad2fSChristophe Ricard struct tpm_chip *chip = dev_get_priv(dev);
2310766ad2fSChristophe Ricard unsigned long start, stop;
2320766ad2fSChristophe Ricard u8 buf = TPM_ACCESS_REQUEST_USE;
2330766ad2fSChristophe Ricard int rc;
2340766ad2fSChristophe Ricard
2350766ad2fSChristophe Ricard rc = tpm_tis_i2c_check_locality(dev, loc);
2360766ad2fSChristophe Ricard if (rc >= 0) {
2370766ad2fSChristophe Ricard debug("%s: Already have locality\n", __func__);
2380766ad2fSChristophe Ricard return loc; /* We already have the locality */
2390766ad2fSChristophe Ricard } else if (rc != -ENOENT) {
2400766ad2fSChristophe Ricard debug("%s: Failed to get locality: %d\n", __func__, rc);
2410766ad2fSChristophe Ricard return rc;
2420766ad2fSChristophe Ricard }
2430766ad2fSChristophe Ricard
2440766ad2fSChristophe Ricard rc = tpm_tis_i2c_write(dev, TPM_ACCESS(loc), &buf, 1);
2450766ad2fSChristophe Ricard if (rc) {
2460766ad2fSChristophe Ricard debug("%s: Failed to write to TPM: %d\n", __func__, rc);
2470766ad2fSChristophe Ricard return rc;
2480766ad2fSChristophe Ricard }
2490766ad2fSChristophe Ricard
2500766ad2fSChristophe Ricard /* Wait for burstcount */
2510766ad2fSChristophe Ricard start = get_timer(0);
2520766ad2fSChristophe Ricard stop = chip->timeout_a;
2530766ad2fSChristophe Ricard do {
2540766ad2fSChristophe Ricard rc = tpm_tis_i2c_check_locality(dev, loc);
2550766ad2fSChristophe Ricard if (rc >= 0) {
2560766ad2fSChristophe Ricard debug("%s: Have locality\n", __func__);
2570766ad2fSChristophe Ricard return loc;
2580766ad2fSChristophe Ricard } else if (rc != -ENOENT) {
2590766ad2fSChristophe Ricard debug("%s: Failed to get locality: %d\n", __func__, rc);
2600766ad2fSChristophe Ricard return rc;
2610766ad2fSChristophe Ricard }
2620766ad2fSChristophe Ricard mdelay(TPM_TIMEOUT_MS);
2630766ad2fSChristophe Ricard } while (get_timer(start) < stop);
2640766ad2fSChristophe Ricard debug("%s: Timeout getting locality: %d\n", __func__, rc);
2650766ad2fSChristophe Ricard
2660766ad2fSChristophe Ricard return rc;
2670766ad2fSChristophe Ricard }
2680766ad2fSChristophe Ricard
tpm_tis_i2c_status(struct udevice * dev)2690766ad2fSChristophe Ricard static u8 tpm_tis_i2c_status(struct udevice *dev)
2700766ad2fSChristophe Ricard {
2710766ad2fSChristophe Ricard struct tpm_chip *chip = dev_get_priv(dev);
2720766ad2fSChristophe Ricard /* NOTE: Since i2c read may fail, return 0 in this case --> time-out */
2730766ad2fSChristophe Ricard u8 buf;
2740766ad2fSChristophe Ricard
2750766ad2fSChristophe Ricard if (tpm_tis_i2c_read(dev, TPM_STS(chip->locality), &buf, 1) < 0)
2760766ad2fSChristophe Ricard return 0;
2770766ad2fSChristophe Ricard else
2780766ad2fSChristophe Ricard return buf;
2790766ad2fSChristophe Ricard }
2800766ad2fSChristophe Ricard
tpm_tis_i2c_ready(struct udevice * dev)2810766ad2fSChristophe Ricard static int tpm_tis_i2c_ready(struct udevice *dev)
2820766ad2fSChristophe Ricard {
2830766ad2fSChristophe Ricard struct tpm_chip *chip = dev_get_priv(dev);
2840766ad2fSChristophe Ricard int rc;
2850766ad2fSChristophe Ricard
2860766ad2fSChristophe Ricard /* This causes the current command to be aborted */
2870766ad2fSChristophe Ricard u8 buf = TPM_STS_COMMAND_READY;
2880766ad2fSChristophe Ricard
2890766ad2fSChristophe Ricard debug("%s\n", __func__);
2900766ad2fSChristophe Ricard rc = tpm_tis_i2c_write_long(dev, TPM_STS(chip->locality), &buf, 1);
2910766ad2fSChristophe Ricard if (rc)
2920766ad2fSChristophe Ricard debug("%s: rc=%d\n", __func__, rc);
2930766ad2fSChristophe Ricard
2940766ad2fSChristophe Ricard return rc;
2950766ad2fSChristophe Ricard }
2960766ad2fSChristophe Ricard
tpm_tis_i2c_get_burstcount(struct udevice * dev)2970766ad2fSChristophe Ricard static ssize_t tpm_tis_i2c_get_burstcount(struct udevice *dev)
2980766ad2fSChristophe Ricard {
2990766ad2fSChristophe Ricard struct tpm_chip *chip = dev_get_priv(dev);
3000766ad2fSChristophe Ricard unsigned long start, stop;
3010766ad2fSChristophe Ricard ssize_t burstcnt;
3020766ad2fSChristophe Ricard u8 addr, buf[3];
3030766ad2fSChristophe Ricard
3040766ad2fSChristophe Ricard /* Wait for burstcount */
3050766ad2fSChristophe Ricard /* XXX: Which timeout value? Spec has 2 answers (c & d) */
3060766ad2fSChristophe Ricard start = get_timer(0);
3070766ad2fSChristophe Ricard stop = chip->timeout_d;
3080766ad2fSChristophe Ricard do {
3090766ad2fSChristophe Ricard /* Note: STS is little endian */
3100766ad2fSChristophe Ricard addr = TPM_STS(chip->locality) + 1;
3110766ad2fSChristophe Ricard if (tpm_tis_i2c_read(dev, addr, buf, 3) < 0)
3120766ad2fSChristophe Ricard burstcnt = 0;
3130766ad2fSChristophe Ricard else
3140766ad2fSChristophe Ricard burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0];
3150766ad2fSChristophe Ricard
3160766ad2fSChristophe Ricard if (burstcnt)
3170766ad2fSChristophe Ricard return burstcnt;
3180766ad2fSChristophe Ricard mdelay(TPM_TIMEOUT_MS);
3190766ad2fSChristophe Ricard } while (get_timer(start) < stop);
3200766ad2fSChristophe Ricard
3210766ad2fSChristophe Ricard return -EBUSY;
3220766ad2fSChristophe Ricard }
3230766ad2fSChristophe Ricard
tpm_tis_i2c_wait_for_stat(struct udevice * dev,u8 mask,unsigned long timeout,int * status)3240766ad2fSChristophe Ricard static int tpm_tis_i2c_wait_for_stat(struct udevice *dev, u8 mask,
3250766ad2fSChristophe Ricard unsigned long timeout, int *status)
3260766ad2fSChristophe Ricard {
3270766ad2fSChristophe Ricard unsigned long start, stop;
3280766ad2fSChristophe Ricard
3290766ad2fSChristophe Ricard /* Check current status */
3300766ad2fSChristophe Ricard *status = tpm_tis_i2c_status(dev);
3310766ad2fSChristophe Ricard if ((*status & mask) == mask)
3320766ad2fSChristophe Ricard return 0;
3330766ad2fSChristophe Ricard
3340766ad2fSChristophe Ricard start = get_timer(0);
3350766ad2fSChristophe Ricard stop = timeout;
3360766ad2fSChristophe Ricard do {
3370766ad2fSChristophe Ricard mdelay(TPM_TIMEOUT_MS);
3380766ad2fSChristophe Ricard *status = tpm_tis_i2c_status(dev);
3390766ad2fSChristophe Ricard if ((*status & mask) == mask)
3400766ad2fSChristophe Ricard return 0;
3410766ad2fSChristophe Ricard } while (get_timer(start) < stop);
3420766ad2fSChristophe Ricard
3430766ad2fSChristophe Ricard return -ETIMEDOUT;
3440766ad2fSChristophe Ricard }
3450766ad2fSChristophe Ricard
tpm_tis_i2c_recv_data(struct udevice * dev,u8 * buf,size_t count)3460766ad2fSChristophe Ricard static int tpm_tis_i2c_recv_data(struct udevice *dev, u8 *buf, size_t count)
3470766ad2fSChristophe Ricard {
3480766ad2fSChristophe Ricard struct tpm_chip *chip = dev_get_priv(dev);
3490766ad2fSChristophe Ricard size_t size = 0;
3500766ad2fSChristophe Ricard ssize_t burstcnt;
3510766ad2fSChristophe Ricard int rc;
3520766ad2fSChristophe Ricard
3530766ad2fSChristophe Ricard while (size < count) {
3540766ad2fSChristophe Ricard burstcnt = tpm_tis_i2c_get_burstcount(dev);
3550766ad2fSChristophe Ricard
3560766ad2fSChristophe Ricard /* burstcount < 0 -> tpm is busy */
3570766ad2fSChristophe Ricard if (burstcnt < 0)
3580766ad2fSChristophe Ricard return burstcnt;
3590766ad2fSChristophe Ricard
3600766ad2fSChristophe Ricard /* Limit received data to max left */
3610766ad2fSChristophe Ricard if (burstcnt > (count - size))
3620766ad2fSChristophe Ricard burstcnt = count - size;
3630766ad2fSChristophe Ricard
3640766ad2fSChristophe Ricard rc = tpm_tis_i2c_read(dev, TPM_DATA_FIFO(chip->locality),
3650766ad2fSChristophe Ricard &(buf[size]), burstcnt);
3660766ad2fSChristophe Ricard if (rc == 0)
3670766ad2fSChristophe Ricard size += burstcnt;
3680766ad2fSChristophe Ricard }
3690766ad2fSChristophe Ricard
3700766ad2fSChristophe Ricard return size;
3710766ad2fSChristophe Ricard }
3720766ad2fSChristophe Ricard
tpm_tis_i2c_recv(struct udevice * dev,u8 * buf,size_t count)3730766ad2fSChristophe Ricard static int tpm_tis_i2c_recv(struct udevice *dev, u8 *buf, size_t count)
3740766ad2fSChristophe Ricard {
3750766ad2fSChristophe Ricard struct tpm_chip *chip = dev_get_priv(dev);
3760766ad2fSChristophe Ricard int size = 0;
3770766ad2fSChristophe Ricard int expected, status;
3780766ad2fSChristophe Ricard int rc;
3790766ad2fSChristophe Ricard
3800766ad2fSChristophe Ricard status = tpm_tis_i2c_status(dev);
3810766ad2fSChristophe Ricard if (status == TPM_STS_COMMAND_READY)
3820766ad2fSChristophe Ricard return -EINTR;
3830766ad2fSChristophe Ricard if ((status & (TPM_STS_DATA_AVAIL | TPM_STS_VALID)) !=
3840766ad2fSChristophe Ricard (TPM_STS_DATA_AVAIL | TPM_STS_VALID))
3850766ad2fSChristophe Ricard return -EAGAIN;
3860766ad2fSChristophe Ricard
3870766ad2fSChristophe Ricard debug("...got it;\n");
3880766ad2fSChristophe Ricard
3890766ad2fSChristophe Ricard /* Read first 10 bytes, including tag, paramsize, and result */
3900766ad2fSChristophe Ricard size = tpm_tis_i2c_recv_data(dev, buf, TPM_HEADER_SIZE);
3910766ad2fSChristophe Ricard if (size < TPM_HEADER_SIZE) {
3920766ad2fSChristophe Ricard debug("Unable to read header\n");
3930766ad2fSChristophe Ricard return size < 0 ? size : -EIO;
3940766ad2fSChristophe Ricard }
3950766ad2fSChristophe Ricard
3960766ad2fSChristophe Ricard expected = get_unaligned_be32(buf + TPM_RSP_SIZE_BYTE);
3970766ad2fSChristophe Ricard if ((size_t)expected > count) {
3980766ad2fSChristophe Ricard debug("Error size=%x, expected=%x, count=%x\n", size, expected,
3990766ad2fSChristophe Ricard count);
4000766ad2fSChristophe Ricard return -ENOSPC;
4010766ad2fSChristophe Ricard }
4020766ad2fSChristophe Ricard
4030766ad2fSChristophe Ricard size += tpm_tis_i2c_recv_data(dev, &buf[TPM_HEADER_SIZE],
4040766ad2fSChristophe Ricard expected - TPM_HEADER_SIZE);
4050766ad2fSChristophe Ricard if (size < expected) {
4060766ad2fSChristophe Ricard debug("Unable to read remainder of result\n");
4070766ad2fSChristophe Ricard return -ETIMEDOUT;
4080766ad2fSChristophe Ricard }
4090766ad2fSChristophe Ricard
4100766ad2fSChristophe Ricard rc = tpm_tis_i2c_wait_for_stat(dev, TPM_STS_VALID, chip->timeout_c,
4110766ad2fSChristophe Ricard &status);
4120766ad2fSChristophe Ricard if (rc)
4130766ad2fSChristophe Ricard return rc;
4140766ad2fSChristophe Ricard if (status & TPM_STS_DATA_AVAIL) { /* Retry? */
4150766ad2fSChristophe Ricard debug("Error left over data\n");
4160766ad2fSChristophe Ricard return -EIO;
4170766ad2fSChristophe Ricard }
4180766ad2fSChristophe Ricard
4190766ad2fSChristophe Ricard return size;
4200766ad2fSChristophe Ricard }
4210766ad2fSChristophe Ricard
tpm_tis_i2c_send(struct udevice * dev,const u8 * buf,size_t len)4220766ad2fSChristophe Ricard static int tpm_tis_i2c_send(struct udevice *dev, const u8 *buf, size_t len)
4230766ad2fSChristophe Ricard {
4240766ad2fSChristophe Ricard struct tpm_chip *chip = dev_get_priv(dev);
4250766ad2fSChristophe Ricard int rc, status;
4260766ad2fSChristophe Ricard size_t burstcnt;
4270766ad2fSChristophe Ricard size_t count = 0;
4280766ad2fSChristophe Ricard int retry = 0;
4290766ad2fSChristophe Ricard u8 sts = TPM_STS_GO;
4300766ad2fSChristophe Ricard
4310766ad2fSChristophe Ricard debug("%s: len=%d\n", __func__, len);
4320766ad2fSChristophe Ricard if (len > TPM_DEV_BUFSIZE)
4330766ad2fSChristophe Ricard return -E2BIG; /* Command is too long for our tpm, sorry */
4340766ad2fSChristophe Ricard
4350766ad2fSChristophe Ricard if (tpm_tis_i2c_request_locality(dev, 0) < 0)
4360766ad2fSChristophe Ricard return -EBUSY;
4370766ad2fSChristophe Ricard
4380766ad2fSChristophe Ricard status = tpm_tis_i2c_status(dev);
4390766ad2fSChristophe Ricard if ((status & TPM_STS_COMMAND_READY) == 0) {
4400766ad2fSChristophe Ricard rc = tpm_tis_i2c_ready(dev);
4410766ad2fSChristophe Ricard if (rc)
4420766ad2fSChristophe Ricard return rc;
4430766ad2fSChristophe Ricard rc = tpm_tis_i2c_wait_for_stat(dev, TPM_STS_COMMAND_READY,
4440766ad2fSChristophe Ricard chip->timeout_b, &status);
4450766ad2fSChristophe Ricard if (rc)
4460766ad2fSChristophe Ricard return rc;
4470766ad2fSChristophe Ricard }
4480766ad2fSChristophe Ricard
4490766ad2fSChristophe Ricard burstcnt = tpm_tis_i2c_get_burstcount(dev);
4500766ad2fSChristophe Ricard
4510766ad2fSChristophe Ricard /* burstcount < 0 -> tpm is busy */
4520766ad2fSChristophe Ricard if (burstcnt < 0)
4530766ad2fSChristophe Ricard return burstcnt;
4540766ad2fSChristophe Ricard
4550766ad2fSChristophe Ricard while (count < len) {
4560766ad2fSChristophe Ricard udelay(300);
4570766ad2fSChristophe Ricard if (burstcnt > len - count)
4580766ad2fSChristophe Ricard burstcnt = len - count;
4590766ad2fSChristophe Ricard
4600766ad2fSChristophe Ricard #ifdef CONFIG_TPM_TIS_I2C_BURST_LIMITATION
4610766ad2fSChristophe Ricard if (retry && burstcnt > CONFIG_TPM_TIS_I2C_BURST_LIMITATION_LEN)
4620766ad2fSChristophe Ricard burstcnt = CONFIG_TPM_TIS_I2C_BURST_LIMITATION_LEN;
4630766ad2fSChristophe Ricard #endif /* CONFIG_TPM_TIS_I2C_BURST_LIMITATION */
4640766ad2fSChristophe Ricard
4650766ad2fSChristophe Ricard rc = tpm_tis_i2c_write(dev, TPM_DATA_FIFO(chip->locality),
4660766ad2fSChristophe Ricard &(buf[count]), burstcnt);
4670766ad2fSChristophe Ricard if (rc == 0)
4680766ad2fSChristophe Ricard count += burstcnt;
4690766ad2fSChristophe Ricard else {
4700766ad2fSChristophe Ricard debug("%s: error\n", __func__);
4710766ad2fSChristophe Ricard if (retry++ > 10)
4720766ad2fSChristophe Ricard return -EIO;
4730766ad2fSChristophe Ricard rc = tpm_tis_i2c_wait_for_stat(dev, TPM_STS_VALID,
4740766ad2fSChristophe Ricard chip->timeout_c,
4750766ad2fSChristophe Ricard &status);
4760766ad2fSChristophe Ricard if (rc)
4770766ad2fSChristophe Ricard return rc;
4780766ad2fSChristophe Ricard
4790766ad2fSChristophe Ricard if ((status & TPM_STS_DATA_EXPECT) == 0)
4800766ad2fSChristophe Ricard return -EIO;
4810766ad2fSChristophe Ricard }
4820766ad2fSChristophe Ricard }
4830766ad2fSChristophe Ricard
4840766ad2fSChristophe Ricard /* Go and do it */
4850766ad2fSChristophe Ricard rc = tpm_tis_i2c_write(dev, TPM_STS(chip->locality), &sts, 1);
4860766ad2fSChristophe Ricard if (rc < 0)
4870766ad2fSChristophe Ricard return rc;
4880766ad2fSChristophe Ricard debug("%s: done, rc=%d\n", __func__, rc);
4890766ad2fSChristophe Ricard
4900766ad2fSChristophe Ricard return len;
4910766ad2fSChristophe Ricard }
4920766ad2fSChristophe Ricard
tpm_tis_i2c_cleanup(struct udevice * dev)4930766ad2fSChristophe Ricard static int tpm_tis_i2c_cleanup(struct udevice *dev)
4940766ad2fSChristophe Ricard {
4950766ad2fSChristophe Ricard struct tpm_chip *chip = dev_get_priv(dev);
4960766ad2fSChristophe Ricard
4970766ad2fSChristophe Ricard tpm_tis_i2c_ready(dev);
4980766ad2fSChristophe Ricard /*
4990766ad2fSChristophe Ricard * The TPM needs some time to clean up here,
5000766ad2fSChristophe Ricard * so we sleep rather than keeping the bus busy
5010766ad2fSChristophe Ricard */
5020766ad2fSChristophe Ricard mdelay(2);
5030766ad2fSChristophe Ricard tpm_tis_i2c_release_locality(dev, chip->locality, 0);
5040766ad2fSChristophe Ricard
5050766ad2fSChristophe Ricard return 0;
5060766ad2fSChristophe Ricard }
5070766ad2fSChristophe Ricard
tpm_tis_i2c_init(struct udevice * dev)5080766ad2fSChristophe Ricard static int tpm_tis_i2c_init(struct udevice *dev)
5090766ad2fSChristophe Ricard {
5100766ad2fSChristophe Ricard struct tpm_chip *chip = dev_get_priv(dev);
5110766ad2fSChristophe Ricard u32 vendor;
5120766ad2fSChristophe Ricard u32 expected_did_vid;
5130766ad2fSChristophe Ricard int rc;
5140766ad2fSChristophe Ricard
5150766ad2fSChristophe Ricard chip->is_open = 1;
5160766ad2fSChristophe Ricard
5170766ad2fSChristophe Ricard /* Default timeouts - these could move to the device tree */
5180766ad2fSChristophe Ricard chip->timeout_a = TIS_SHORT_TIMEOUT_MS;
5190766ad2fSChristophe Ricard chip->timeout_b = TIS_LONG_TIMEOUT_MS;
5200766ad2fSChristophe Ricard chip->timeout_c = TIS_SHORT_TIMEOUT_MS;
5210766ad2fSChristophe Ricard chip->timeout_d = TIS_SHORT_TIMEOUT_MS;
5220766ad2fSChristophe Ricard
5230766ad2fSChristophe Ricard rc = tpm_tis_i2c_request_locality(dev, 0);
5240766ad2fSChristophe Ricard if (rc < 0)
5250766ad2fSChristophe Ricard return rc;
5260766ad2fSChristophe Ricard
5270766ad2fSChristophe Ricard /* Read four bytes from DID_VID register */
5280766ad2fSChristophe Ricard if (tpm_tis_i2c_read(dev, TPM_DID_VID(0), (uchar *)&vendor, 4) < 0) {
5290766ad2fSChristophe Ricard tpm_tis_i2c_release_locality(dev, 0, 1);
5300766ad2fSChristophe Ricard return -EIO;
5310766ad2fSChristophe Ricard }
5320766ad2fSChristophe Ricard
5330766ad2fSChristophe Ricard if (chip->chip_type == SLB9635) {
5340766ad2fSChristophe Ricard vendor = be32_to_cpu(vendor);
5350766ad2fSChristophe Ricard expected_did_vid = TPM_TIS_I2C_DID_VID_9635;
5360766ad2fSChristophe Ricard } else {
5370766ad2fSChristophe Ricard /* device id and byte order has changed for newer i2c tpms */
5380766ad2fSChristophe Ricard expected_did_vid = TPM_TIS_I2C_DID_VID_9645;
5390766ad2fSChristophe Ricard }
5400766ad2fSChristophe Ricard
5410766ad2fSChristophe Ricard if (chip->chip_type != UNKNOWN && vendor != expected_did_vid) {
542*90aa625cSMasahiro Yamada pr_err("Vendor id did not match! ID was %08x\n", vendor);
5430766ad2fSChristophe Ricard return -ENODEV;
5440766ad2fSChristophe Ricard }
5450766ad2fSChristophe Ricard
5460766ad2fSChristophe Ricard chip->vend_dev = vendor;
5470766ad2fSChristophe Ricard debug("1.2 TPM (chip type %s device-id 0x%X)\n",
5480766ad2fSChristophe Ricard chip_name[chip->chip_type], vendor >> 16);
5490766ad2fSChristophe Ricard
5500766ad2fSChristophe Ricard /*
5510766ad2fSChristophe Ricard * A timeout query to TPM can be placed here.
5520766ad2fSChristophe Ricard * Standard timeout values are used so far
5530766ad2fSChristophe Ricard */
5540766ad2fSChristophe Ricard
5550766ad2fSChristophe Ricard return 0;
5560766ad2fSChristophe Ricard }
5570766ad2fSChristophe Ricard
tpm_tis_i2c_open(struct udevice * dev)5580766ad2fSChristophe Ricard static int tpm_tis_i2c_open(struct udevice *dev)
5590766ad2fSChristophe Ricard {
5600766ad2fSChristophe Ricard struct tpm_chip *chip = dev_get_priv(dev);
5610766ad2fSChristophe Ricard int rc;
5620766ad2fSChristophe Ricard
5630766ad2fSChristophe Ricard debug("%s: start\n", __func__);
5640766ad2fSChristophe Ricard if (chip->is_open)
5650766ad2fSChristophe Ricard return -EBUSY;
5660766ad2fSChristophe Ricard rc = tpm_tis_i2c_init(dev);
5670766ad2fSChristophe Ricard if (rc < 0)
5680766ad2fSChristophe Ricard chip->is_open = 0;
5690766ad2fSChristophe Ricard
5700766ad2fSChristophe Ricard return rc;
5710766ad2fSChristophe Ricard }
5720766ad2fSChristophe Ricard
tpm_tis_i2c_close(struct udevice * dev)5730766ad2fSChristophe Ricard static int tpm_tis_i2c_close(struct udevice *dev)
5740766ad2fSChristophe Ricard {
5750766ad2fSChristophe Ricard struct tpm_chip *chip = dev_get_priv(dev);
5760766ad2fSChristophe Ricard
5770766ad2fSChristophe Ricard if (chip->is_open) {
5780766ad2fSChristophe Ricard tpm_tis_i2c_release_locality(dev, chip->locality, 1);
5790766ad2fSChristophe Ricard chip->is_open = 0;
5800766ad2fSChristophe Ricard chip->vend_dev = 0;
5810766ad2fSChristophe Ricard }
5820766ad2fSChristophe Ricard
5830766ad2fSChristophe Ricard return 0;
5840766ad2fSChristophe Ricard }
5850766ad2fSChristophe Ricard
tpm_tis_get_desc(struct udevice * dev,char * buf,int size)5860766ad2fSChristophe Ricard static int tpm_tis_get_desc(struct udevice *dev, char *buf, int size)
5870766ad2fSChristophe Ricard {
5880766ad2fSChristophe Ricard struct tpm_chip *chip = dev_get_priv(dev);
5890766ad2fSChristophe Ricard
5900766ad2fSChristophe Ricard if (size < 50)
5910766ad2fSChristophe Ricard return -ENOSPC;
5920766ad2fSChristophe Ricard
5930766ad2fSChristophe Ricard return snprintf(buf, size, "1.2 TPM (%s, chip type %s device-id 0x%x)",
5940766ad2fSChristophe Ricard chip->is_open ? "open" : "closed",
5950766ad2fSChristophe Ricard chip_name[chip->chip_type],
5960766ad2fSChristophe Ricard chip->vend_dev >> 16);
5970766ad2fSChristophe Ricard }
5980766ad2fSChristophe Ricard
tpm_tis_i2c_probe(struct udevice * dev)5990766ad2fSChristophe Ricard static int tpm_tis_i2c_probe(struct udevice *dev)
6000766ad2fSChristophe Ricard {
6010766ad2fSChristophe Ricard struct tpm_chip_priv *uc_priv = dev_get_uclass_priv(dev);
6020766ad2fSChristophe Ricard struct tpm_chip *chip = dev_get_priv(dev);
6030766ad2fSChristophe Ricard
6040766ad2fSChristophe Ricard chip->chip_type = dev_get_driver_data(dev);
6050766ad2fSChristophe Ricard
6060766ad2fSChristophe Ricard /* TODO: These need to be checked and tuned */
6070766ad2fSChristophe Ricard uc_priv->duration_ms[TPM_SHORT] = TIS_SHORT_TIMEOUT_MS;
6080766ad2fSChristophe Ricard uc_priv->duration_ms[TPM_MEDIUM] = TIS_LONG_TIMEOUT_MS;
6090766ad2fSChristophe Ricard uc_priv->duration_ms[TPM_LONG] = TIS_LONG_TIMEOUT_MS;
6100766ad2fSChristophe Ricard uc_priv->retry_time_ms = TPM_TIMEOUT_MS;
6110766ad2fSChristophe Ricard
6120766ad2fSChristophe Ricard return 0;
6130766ad2fSChristophe Ricard }
6140766ad2fSChristophe Ricard
6150766ad2fSChristophe Ricard static const struct tpm_ops tpm_tis_i2c_ops = {
6160766ad2fSChristophe Ricard .open = tpm_tis_i2c_open,
6170766ad2fSChristophe Ricard .close = tpm_tis_i2c_close,
6180766ad2fSChristophe Ricard .get_desc = tpm_tis_get_desc,
6190766ad2fSChristophe Ricard .send = tpm_tis_i2c_send,
6200766ad2fSChristophe Ricard .recv = tpm_tis_i2c_recv,
6210766ad2fSChristophe Ricard .cleanup = tpm_tis_i2c_cleanup,
6220766ad2fSChristophe Ricard };
6230766ad2fSChristophe Ricard
6240766ad2fSChristophe Ricard static const struct udevice_id tpm_tis_i2c_ids[] = {
6250766ad2fSChristophe Ricard { .compatible = "infineon,slb9635tt", .data = SLB9635 },
6260766ad2fSChristophe Ricard { .compatible = "infineon,slb9645tt", .data = SLB9645 },
6270766ad2fSChristophe Ricard { }
6280766ad2fSChristophe Ricard };
6290766ad2fSChristophe Ricard
6300766ad2fSChristophe Ricard U_BOOT_DRIVER(tpm_tis_i2c) = {
6310766ad2fSChristophe Ricard .name = "tpm_tis_infineon",
6320766ad2fSChristophe Ricard .id = UCLASS_TPM,
6330766ad2fSChristophe Ricard .of_match = tpm_tis_i2c_ids,
6340766ad2fSChristophe Ricard .ops = &tpm_tis_i2c_ops,
6350766ad2fSChristophe Ricard .probe = tpm_tis_i2c_probe,
6360766ad2fSChristophe Ricard .priv_auto_alloc_size = sizeof(struct tpm_chip),
6370766ad2fSChristophe Ricard };
638