From: Stefano Radaelli <[email protected]> The common TPM Device Tree binding already documents resets and reset-gpios, but the TIS I2C driver never requests a reset control. As a result, an I2C TPM held in reset by board wiring remains inaccessible and the first register access during probe fails.
Request the optional reset control and deassert it before communicating with the TPM. This keeps existing boards without a reset line unchanged while allowing platforms using resets or reset-gpios to release the TPM before probe continues. Tested on a Variscite DART-MX95 with an ST33KTPM2XI2C TPM using reset-gpios. Signed-off-by: Stefano Radaelli <[email protected]> --- drivers/char/tpm/tpm_tis_i2c.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/char/tpm/tpm_tis_i2c.c b/drivers/char/tpm/tpm_tis_i2c.c index d55f30fef00a..cde0b093ed58 100644 --- a/drivers/char/tpm/tpm_tis_i2c.c +++ b/drivers/char/tpm/tpm_tis_i2c.c @@ -12,6 +12,7 @@ #include <linux/i2c.h> #include <linux/crc-ccitt.h> +#include <linux/reset.h> #include "tpm_tis_core.h" /* TPM registers */ @@ -330,6 +331,7 @@ static const struct tpm_tis_phy_ops tpm_i2c_phy_ops = { static int tpm_tis_i2c_probe(struct i2c_client *dev) { struct tpm_tis_i2c_phy *phy; + struct reset_control *reset; const u8 crc_enable = 1; const u8 locality = 0; int ret; @@ -346,6 +348,16 @@ static int tpm_tis_i2c_probe(struct i2c_client *dev) set_bit(TPM_TIS_DEFAULT_CANCELLATION, &phy->priv.flags); phy->i2c_client = dev; + reset = devm_reset_control_get_optional_exclusive(&dev->dev, NULL); + if (IS_ERR(reset)) + return dev_err_probe(&dev->dev, PTR_ERR(reset), + "failed to get reset control\n"); + + ret = reset_control_deassert(reset); + if (ret) + return dev_err_probe(&dev->dev, ret, + "failed to deassert reset\n"); + /* must precede all communication with the tpm */ ret = tpm_tis_i2c_init_guard_time(phy); if (ret) -- 2.47.3

