Lines Matching +full:phy +full:- +full:i2c
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2014-2021 Nuvoton Technology corporation
4 * Copyright (C) 2019-2022 Infineon Technologies AG
13 #include <linux/i2c.h>
14 #include <linux/crc-ccitt.h>
27 /* TIS-compatible register address to avoid clash with TPM_ACCESS (0x00) */
30 /* Mask to extract the I2C register from TIS register addresses */
37 /* Guard Time of 250µs after I2C slave NACK */
77 * those addresses need to mapped to the registers defined for I2C TPMs in
78 * Table 51 "I2C-TPM Register Overview".
82 * since the corresponding I2C registers have been moved around. TPM_LOC_SEL is
83 * only defined for I2C TPMs and is also mapped explicitly here to distinguish
110 struct tpm_tis_i2c_phy *phy = to_tpm_tis_i2c_phy(data); in tpm_tis_i2c_retry_transfer_until_ack() local
115 if (msg->flags & I2C_M_RD) in tpm_tis_i2c_retry_transfer_until_ack()
116 guard_time = phy->guard_time_read; in tpm_tis_i2c_retry_transfer_until_ack()
118 guard_time = phy->guard_time_write; in tpm_tis_i2c_retry_transfer_until_ack()
121 ret = i2c_transfer(phy->i2c_client->adapter, msg, 1); in tpm_tis_i2c_retry_transfer_until_ack()
125 usleep_range(phy->guard_time_min, phy->guard_time_max); in tpm_tis_i2c_retry_transfer_until_ack()
175 pr_debug("TPM I2C read of register 0x%02x failed sanity check: 0x%x\n", reg, value); in tpm_tis_i2c_sanity_check_read()
176 return -EIO; in tpm_tis_i2c_sanity_check_read()
185 struct tpm_tis_i2c_phy *phy = to_tpm_tis_i2c_phy(data); in tpm_tis_i2c_read_bytes() local
186 struct i2c_msg msg = { .addr = phy->i2c_client->addr }; in tpm_tis_i2c_read_bytes()
205 msg.len = len - read; in tpm_tis_i2c_read_bytes()
229 struct tpm_tis_i2c_phy *phy = to_tpm_tis_i2c_phy(data); in tpm_tis_i2c_write_bytes() local
230 struct i2c_msg msg = { .addr = phy->i2c_client->addr }; in tpm_tis_i2c_write_bytes()
235 if (len > TPM_BUFSIZE - 1) in tpm_tis_i2c_write_bytes()
236 return -EIO; in tpm_tis_i2c_write_bytes()
238 phy->io_buf[0] = reg; in tpm_tis_i2c_write_bytes()
239 msg.buf = phy->io_buf; in tpm_tis_i2c_write_bytes()
242 msg.len = sizeof(reg) + len - wrote; in tpm_tis_i2c_write_bytes()
246 memcpy(phy->io_buf + sizeof(reg), value + wrote, in tpm_tis_i2c_write_bytes()
247 msg.len - sizeof(reg)); in tpm_tis_i2c_write_bytes()
252 wrote += msg.len - sizeof(reg); in tpm_tis_i2c_write_bytes()
271 return -EIO; in tpm_tis_i2c_verify_crc()
278 * After each I2C operation, the TPM might require the master to wait.
279 * The time period is vendor-specific and must be read from the
282 * Before the Guard Time is read (or after the TPM failed to send an I2C NACK),
286 * - SR: <I2C read with repeated start> <guard time> <I2C read>
287 * - RR: <I2C read> <guard time> <I2C read>
288 * - RW: <I2C read> <guard time> <I2C write>
289 * - WR: <I2C write> <guard time> <I2C read>
290 * - WW: <I2C write> <guard time> <I2C write>
294 static int tpm_tis_i2c_init_guard_time(struct tpm_tis_i2c_phy *phy) in tpm_tis_i2c_init_guard_time() argument
299 phy->guard_time_read = true; in tpm_tis_i2c_init_guard_time()
300 phy->guard_time_write = true; in tpm_tis_i2c_init_guard_time()
301 phy->guard_time_min = GUARD_TIME_DEFAULT_MIN; in tpm_tis_i2c_init_guard_time()
302 phy->guard_time_max = GUARD_TIME_DEFAULT_MAX; in tpm_tis_i2c_init_guard_time()
304 ret = tpm_tis_i2c_read_bytes(&phy->priv, TPM_I2C_INTERFACE_CAPABILITY, in tpm_tis_i2c_init_guard_time()
310 phy->guard_time_read = (i2c_caps & TPM_GUARD_TIME_RR_MASK) || in tpm_tis_i2c_init_guard_time()
312 phy->guard_time_write = (i2c_caps & TPM_GUARD_TIME_WR_MASK) || in tpm_tis_i2c_init_guard_time()
314 phy->guard_time_min = (i2c_caps & TPM_GUARD_TIME_MIN_MASK) >> in tpm_tis_i2c_init_guard_time()
317 phy->guard_time_max = phy->guard_time_min + phy->guard_time_min / 5; in tpm_tis_i2c_init_guard_time()
332 struct tpm_tis_i2c_phy *phy; in tpm_tis_i2c_probe() local
337 phy = devm_kzalloc(&dev->dev, sizeof(struct tpm_tis_i2c_phy), in tpm_tis_i2c_probe()
339 if (!phy) in tpm_tis_i2c_probe()
340 return -ENOMEM; in tpm_tis_i2c_probe()
342 phy->io_buf = devm_kzalloc(&dev->dev, TPM_BUFSIZE, GFP_KERNEL); in tpm_tis_i2c_probe()
343 if (!phy->io_buf) in tpm_tis_i2c_probe()
344 return -ENOMEM; in tpm_tis_i2c_probe()
346 set_bit(TPM_TIS_DEFAULT_CANCELLATION, &phy->priv.flags); in tpm_tis_i2c_probe()
347 phy->i2c_client = dev; in tpm_tis_i2c_probe()
350 ret = tpm_tis_i2c_init_guard_time(phy); in tpm_tis_i2c_probe()
354 ret = tpm_tis_i2c_write_bytes(&phy->priv, TPM_LOC_SEL, sizeof(locality), in tpm_tis_i2c_probe()
359 ret = tpm_tis_i2c_write_bytes(&phy->priv, TPM_I2C_DATA_CSUM_ENABLE, in tpm_tis_i2c_probe()
365 return tpm_tis_core_init(&dev->dev, &phy->priv, -1, &tpm_i2c_phy_ops, in tpm_tis_i2c_probe()
381 MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_id);
387 { .compatible = "tcg,tpm-tis-i2c", },
405 MODULE_DESCRIPTION("TPM Driver for native I2C access");