13a253caaSDuncan Laurie // SPDX-License-Identifier: GPL-2.0
23a253caaSDuncan Laurie /*
33a253caaSDuncan Laurie * Copyright 2020 Google Inc.
43a253caaSDuncan Laurie *
53a253caaSDuncan Laurie * Based on Infineon TPM driver by Peter Huewe.
63a253caaSDuncan Laurie *
73a253caaSDuncan Laurie * cr50 is a firmware for H1 secure modules that requires special
83a253caaSDuncan Laurie * handling for the I2C interface.
93a253caaSDuncan Laurie *
103a253caaSDuncan Laurie * - Use an interrupt for transaction status instead of hardcoded delays.
113a253caaSDuncan Laurie * - Must use write+wait+read read protocol.
123a253caaSDuncan Laurie * - All 4 bytes of status register must be read/written at once.
133a253caaSDuncan Laurie * - Burst count max is 63 bytes, and burst count behaves slightly differently
143a253caaSDuncan Laurie * than other I2C TPMs.
153a253caaSDuncan Laurie * - When reading from FIFO the full burstcnt must be read instead of just
163a253caaSDuncan Laurie * reading header and determining the remainder.
173a253caaSDuncan Laurie */
183a253caaSDuncan Laurie
193a253caaSDuncan Laurie #include <linux/acpi.h>
203a253caaSDuncan Laurie #include <linux/completion.h>
213a253caaSDuncan Laurie #include <linux/i2c.h>
223a253caaSDuncan Laurie #include <linux/interrupt.h>
233a253caaSDuncan Laurie #include <linux/module.h>
243a253caaSDuncan Laurie #include <linux/pm.h>
253a253caaSDuncan Laurie #include <linux/slab.h>
263a253caaSDuncan Laurie #include <linux/wait.h>
273a253caaSDuncan Laurie
283a253caaSDuncan Laurie #include "tpm_tis_core.h"
293a253caaSDuncan Laurie
303a253caaSDuncan Laurie #define TPM_CR50_MAX_BUFSIZE 64
313a253caaSDuncan Laurie #define TPM_CR50_TIMEOUT_SHORT_MS 2 /* Short timeout during transactions */
323a253caaSDuncan Laurie #define TPM_CR50_TIMEOUT_NOIRQ_MS 20 /* Timeout for TPM ready without IRQ */
333a253caaSDuncan Laurie #define TPM_CR50_I2C_DID_VID 0x00281ae0L /* Device and vendor ID reg value */
349c438fdeSJes B. Klinke #define TPM_TI50_I2C_DID_VID 0x504a6666L /* Device and vendor ID reg value */
353a253caaSDuncan Laurie #define TPM_CR50_I2C_MAX_RETRIES 3 /* Max retries due to I2C errors */
363a253caaSDuncan Laurie #define TPM_CR50_I2C_RETRY_DELAY_LO 55 /* Min usecs between retries on I2C */
373a253caaSDuncan Laurie #define TPM_CR50_I2C_RETRY_DELAY_HI 65 /* Max usecs between retries on I2C */
383a253caaSDuncan Laurie
393a253caaSDuncan Laurie #define TPM_I2C_ACCESS(l) (0x0000 | ((l) << 4))
403a253caaSDuncan Laurie #define TPM_I2C_STS(l) (0x0001 | ((l) << 4))
413a253caaSDuncan Laurie #define TPM_I2C_DATA_FIFO(l) (0x0005 | ((l) << 4))
423a253caaSDuncan Laurie #define TPM_I2C_DID_VID(l) (0x0006 | ((l) << 4))
433a253caaSDuncan Laurie
443a253caaSDuncan Laurie /**
453a253caaSDuncan Laurie * struct tpm_i2c_cr50_priv_data - Driver private data.
463a253caaSDuncan Laurie * @irq: Irq number used for this chip.
473a253caaSDuncan Laurie * If irq <= 0, then a fixed timeout is used instead of waiting for irq.
483a253caaSDuncan Laurie * @tpm_ready: Struct used by irq handler to signal R/W readiness.
493a253caaSDuncan Laurie * @buf: Buffer used for i2c writes, with i2c address prepended to content.
503a253caaSDuncan Laurie *
513a253caaSDuncan Laurie * Private driver struct used by kernel threads and interrupt context.
523a253caaSDuncan Laurie */
533a253caaSDuncan Laurie struct tpm_i2c_cr50_priv_data {
543a253caaSDuncan Laurie int irq;
553a253caaSDuncan Laurie struct completion tpm_ready;
563a253caaSDuncan Laurie u8 buf[TPM_CR50_MAX_BUFSIZE];
573a253caaSDuncan Laurie };
583a253caaSDuncan Laurie
593a253caaSDuncan Laurie /**
603a253caaSDuncan Laurie * tpm_cr50_i2c_int_handler() - cr50 interrupt handler.
613a253caaSDuncan Laurie * @dummy: Unused parameter.
623a253caaSDuncan Laurie * @tpm_info: TPM chip information.
633a253caaSDuncan Laurie *
643a253caaSDuncan Laurie * The cr50 interrupt handler signals waiting threads that the
653a253caaSDuncan Laurie * interrupt has been asserted. It does not do any interrupt triggered
663a253caaSDuncan Laurie * processing but is instead used to avoid fixed delays.
673a253caaSDuncan Laurie *
683a253caaSDuncan Laurie * Return:
693a253caaSDuncan Laurie * IRQ_HANDLED signifies irq was handled by this device.
703a253caaSDuncan Laurie */
tpm_cr50_i2c_int_handler(int dummy,void * tpm_info)713a253caaSDuncan Laurie static irqreturn_t tpm_cr50_i2c_int_handler(int dummy, void *tpm_info)
723a253caaSDuncan Laurie {
733a253caaSDuncan Laurie struct tpm_chip *chip = tpm_info;
743a253caaSDuncan Laurie struct tpm_i2c_cr50_priv_data *priv = dev_get_drvdata(&chip->dev);
753a253caaSDuncan Laurie
763a253caaSDuncan Laurie complete(&priv->tpm_ready);
773a253caaSDuncan Laurie
783a253caaSDuncan Laurie return IRQ_HANDLED;
793a253caaSDuncan Laurie }
803a253caaSDuncan Laurie
813a253caaSDuncan Laurie /**
823a253caaSDuncan Laurie * tpm_cr50_i2c_wait_tpm_ready() - Wait for tpm to signal ready.
833a253caaSDuncan Laurie * @chip: A TPM chip.
843a253caaSDuncan Laurie *
853a253caaSDuncan Laurie * Wait for completion interrupt if available, otherwise use a fixed
863a253caaSDuncan Laurie * delay for the TPM to be ready.
873a253caaSDuncan Laurie *
883a253caaSDuncan Laurie * Return:
893a253caaSDuncan Laurie * - 0: Success.
903a253caaSDuncan Laurie * - -errno: A POSIX error code.
913a253caaSDuncan Laurie */
tpm_cr50_i2c_wait_tpm_ready(struct tpm_chip * chip)923a253caaSDuncan Laurie static int tpm_cr50_i2c_wait_tpm_ready(struct tpm_chip *chip)
933a253caaSDuncan Laurie {
943a253caaSDuncan Laurie struct tpm_i2c_cr50_priv_data *priv = dev_get_drvdata(&chip->dev);
953a253caaSDuncan Laurie
963a253caaSDuncan Laurie /* Use a safe fixed delay if interrupt is not supported */
973a253caaSDuncan Laurie if (priv->irq <= 0) {
983a253caaSDuncan Laurie msleep(TPM_CR50_TIMEOUT_NOIRQ_MS);
993a253caaSDuncan Laurie return 0;
1003a253caaSDuncan Laurie }
1013a253caaSDuncan Laurie
1023a253caaSDuncan Laurie /* Wait for interrupt to indicate TPM is ready to respond */
10396785d63SMark Hasemeyer if (!wait_for_completion_timeout(&priv->tpm_ready, chip->timeout_a)) {
1043a253caaSDuncan Laurie dev_warn(&chip->dev, "Timeout waiting for TPM ready\n");
1053a253caaSDuncan Laurie return -ETIMEDOUT;
1063a253caaSDuncan Laurie }
1073a253caaSDuncan Laurie
1083a253caaSDuncan Laurie return 0;
1093a253caaSDuncan Laurie }
1103a253caaSDuncan Laurie
1113a253caaSDuncan Laurie /**
1123a253caaSDuncan Laurie * tpm_cr50_i2c_enable_tpm_irq() - Enable TPM irq.
1133a253caaSDuncan Laurie * @chip: A TPM chip.
1143a253caaSDuncan Laurie */
tpm_cr50_i2c_enable_tpm_irq(struct tpm_chip * chip)1153a253caaSDuncan Laurie static void tpm_cr50_i2c_enable_tpm_irq(struct tpm_chip *chip)
1163a253caaSDuncan Laurie {
1173a253caaSDuncan Laurie struct tpm_i2c_cr50_priv_data *priv = dev_get_drvdata(&chip->dev);
1183a253caaSDuncan Laurie
1193a253caaSDuncan Laurie if (priv->irq > 0) {
1203a253caaSDuncan Laurie reinit_completion(&priv->tpm_ready);
1213a253caaSDuncan Laurie enable_irq(priv->irq);
1223a253caaSDuncan Laurie }
1233a253caaSDuncan Laurie }
1243a253caaSDuncan Laurie
1253a253caaSDuncan Laurie /**
1263a253caaSDuncan Laurie * tpm_cr50_i2c_disable_tpm_irq() - Disable TPM irq.
1273a253caaSDuncan Laurie * @chip: A TPM chip.
1283a253caaSDuncan Laurie */
tpm_cr50_i2c_disable_tpm_irq(struct tpm_chip * chip)1293a253caaSDuncan Laurie static void tpm_cr50_i2c_disable_tpm_irq(struct tpm_chip *chip)
1303a253caaSDuncan Laurie {
1313a253caaSDuncan Laurie struct tpm_i2c_cr50_priv_data *priv = dev_get_drvdata(&chip->dev);
1323a253caaSDuncan Laurie
1333a253caaSDuncan Laurie if (priv->irq > 0)
1343a253caaSDuncan Laurie disable_irq(priv->irq);
1353a253caaSDuncan Laurie }
1363a253caaSDuncan Laurie
1373a253caaSDuncan Laurie /**
1383a253caaSDuncan Laurie * tpm_cr50_i2c_transfer_message() - Transfer a message over i2c.
1393a253caaSDuncan Laurie * @dev: Device information.
1403a253caaSDuncan Laurie * @adapter: I2C adapter.
1413a253caaSDuncan Laurie * @msg: Message to transfer.
1423a253caaSDuncan Laurie *
1433a253caaSDuncan Laurie * Call unlocked i2c transfer routine with the provided parameters and
1443a253caaSDuncan Laurie * retry in case of bus errors.
1453a253caaSDuncan Laurie *
1463a253caaSDuncan Laurie * Return:
1473a253caaSDuncan Laurie * - 0: Success.
1483a253caaSDuncan Laurie * - -errno: A POSIX error code.
1493a253caaSDuncan Laurie */
tpm_cr50_i2c_transfer_message(struct device * dev,struct i2c_adapter * adapter,struct i2c_msg * msg)1503a253caaSDuncan Laurie static int tpm_cr50_i2c_transfer_message(struct device *dev,
1513a253caaSDuncan Laurie struct i2c_adapter *adapter,
1523a253caaSDuncan Laurie struct i2c_msg *msg)
1533a253caaSDuncan Laurie {
1543a253caaSDuncan Laurie unsigned int try;
1553a253caaSDuncan Laurie int rc;
1563a253caaSDuncan Laurie
1573a253caaSDuncan Laurie for (try = 0; try < TPM_CR50_I2C_MAX_RETRIES; try++) {
1583a253caaSDuncan Laurie rc = __i2c_transfer(adapter, msg, 1);
1593a253caaSDuncan Laurie if (rc == 1)
1603a253caaSDuncan Laurie return 0; /* Successfully transferred the message */
1613a253caaSDuncan Laurie if (try)
1623a253caaSDuncan Laurie dev_warn(dev, "i2c transfer failed (attempt %d/%d): %d\n",
1633a253caaSDuncan Laurie try + 1, TPM_CR50_I2C_MAX_RETRIES, rc);
1643a253caaSDuncan Laurie usleep_range(TPM_CR50_I2C_RETRY_DELAY_LO, TPM_CR50_I2C_RETRY_DELAY_HI);
1653a253caaSDuncan Laurie }
1663a253caaSDuncan Laurie
1673a253caaSDuncan Laurie /* No i2c message transferred */
1683a253caaSDuncan Laurie return -EIO;
1693a253caaSDuncan Laurie }
1703a253caaSDuncan Laurie
1713a253caaSDuncan Laurie /**
1723a253caaSDuncan Laurie * tpm_cr50_i2c_read() - Read from TPM register.
1733a253caaSDuncan Laurie * @chip: A TPM chip.
1743a253caaSDuncan Laurie * @addr: Register address to read from.
1753a253caaSDuncan Laurie * @buffer: Read destination, provided by caller.
1763a253caaSDuncan Laurie * @len: Number of bytes to read.
1773a253caaSDuncan Laurie *
1783a253caaSDuncan Laurie * Sends the register address byte to the TPM, then waits until TPM
1793a253caaSDuncan Laurie * is ready via interrupt signal or timeout expiration, then 'len'
1803a253caaSDuncan Laurie * bytes are read from TPM response into the provided 'buffer'.
1813a253caaSDuncan Laurie *
1823a253caaSDuncan Laurie * Return:
1833a253caaSDuncan Laurie * - 0: Success.
1843a253caaSDuncan Laurie * - -errno: A POSIX error code.
1853a253caaSDuncan Laurie */
tpm_cr50_i2c_read(struct tpm_chip * chip,u8 addr,u8 * buffer,size_t len)1863a253caaSDuncan Laurie static int tpm_cr50_i2c_read(struct tpm_chip *chip, u8 addr, u8 *buffer, size_t len)
1873a253caaSDuncan Laurie {
1883a253caaSDuncan Laurie struct i2c_client *client = to_i2c_client(chip->dev.parent);
1893a253caaSDuncan Laurie struct i2c_msg msg_reg_addr = {
1903a253caaSDuncan Laurie .addr = client->addr,
1913a253caaSDuncan Laurie .len = 1,
1923a253caaSDuncan Laurie .buf = &addr
1933a253caaSDuncan Laurie };
1943a253caaSDuncan Laurie struct i2c_msg msg_response = {
1953a253caaSDuncan Laurie .addr = client->addr,
1963a253caaSDuncan Laurie .flags = I2C_M_RD,
1973a253caaSDuncan Laurie .len = len,
1983a253caaSDuncan Laurie .buf = buffer
1993a253caaSDuncan Laurie };
2003a253caaSDuncan Laurie int rc;
2013a253caaSDuncan Laurie
2023a253caaSDuncan Laurie i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
2033a253caaSDuncan Laurie
2043a253caaSDuncan Laurie /* Prepare for completion interrupt */
2053a253caaSDuncan Laurie tpm_cr50_i2c_enable_tpm_irq(chip);
2063a253caaSDuncan Laurie
2073a253caaSDuncan Laurie /* Send the register address byte to the TPM */
2083a253caaSDuncan Laurie rc = tpm_cr50_i2c_transfer_message(&chip->dev, client->adapter, &msg_reg_addr);
2093a253caaSDuncan Laurie if (rc < 0)
2103a253caaSDuncan Laurie goto out;
2113a253caaSDuncan Laurie
2123a253caaSDuncan Laurie /* Wait for TPM to be ready with response data */
2133a253caaSDuncan Laurie rc = tpm_cr50_i2c_wait_tpm_ready(chip);
2143a253caaSDuncan Laurie if (rc < 0)
2153a253caaSDuncan Laurie goto out;
2163a253caaSDuncan Laurie
2173a253caaSDuncan Laurie /* Read response data from the TPM */
2183a253caaSDuncan Laurie rc = tpm_cr50_i2c_transfer_message(&chip->dev, client->adapter, &msg_response);
2193a253caaSDuncan Laurie
2203a253caaSDuncan Laurie out:
2213a253caaSDuncan Laurie tpm_cr50_i2c_disable_tpm_irq(chip);
2223a253caaSDuncan Laurie i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
2233a253caaSDuncan Laurie
2243a253caaSDuncan Laurie if (rc < 0)
2253a253caaSDuncan Laurie return rc;
2263a253caaSDuncan Laurie
2273a253caaSDuncan Laurie return 0;
2283a253caaSDuncan Laurie }
2293a253caaSDuncan Laurie
2303a253caaSDuncan Laurie /**
2313a253caaSDuncan Laurie * tpm_cr50_i2c_write()- Write to TPM register.
2323a253caaSDuncan Laurie * @chip: A TPM chip.
2333a253caaSDuncan Laurie * @addr: Register address to write to.
2343a253caaSDuncan Laurie * @buffer: Data to write.
2353a253caaSDuncan Laurie * @len: Number of bytes to write.
2363a253caaSDuncan Laurie *
2373a253caaSDuncan Laurie * The provided address is prepended to the data in 'buffer', the
2383a253caaSDuncan Laurie * cobined address+data is sent to the TPM, then wait for TPM to
2393a253caaSDuncan Laurie * indicate it is done writing.
2403a253caaSDuncan Laurie *
2413a253caaSDuncan Laurie * Return:
2423a253caaSDuncan Laurie * - 0: Success.
2433a253caaSDuncan Laurie * - -errno: A POSIX error code.
2443a253caaSDuncan Laurie */
tpm_cr50_i2c_write(struct tpm_chip * chip,u8 addr,u8 * buffer,size_t len)2453a253caaSDuncan Laurie static int tpm_cr50_i2c_write(struct tpm_chip *chip, u8 addr, u8 *buffer,
2463a253caaSDuncan Laurie size_t len)
2473a253caaSDuncan Laurie {
2483a253caaSDuncan Laurie struct tpm_i2c_cr50_priv_data *priv = dev_get_drvdata(&chip->dev);
2493a253caaSDuncan Laurie struct i2c_client *client = to_i2c_client(chip->dev.parent);
2503a253caaSDuncan Laurie struct i2c_msg msg = {
2513a253caaSDuncan Laurie .addr = client->addr,
2523a253caaSDuncan Laurie .len = len + 1,
2533a253caaSDuncan Laurie .buf = priv->buf
2543a253caaSDuncan Laurie };
2553a253caaSDuncan Laurie int rc;
2563a253caaSDuncan Laurie
2573a253caaSDuncan Laurie if (len > TPM_CR50_MAX_BUFSIZE - 1)
2583a253caaSDuncan Laurie return -EINVAL;
2593a253caaSDuncan Laurie
2603a253caaSDuncan Laurie /* Prepend the 'register address' to the buffer */
2613a253caaSDuncan Laurie priv->buf[0] = addr;
2623a253caaSDuncan Laurie memcpy(priv->buf + 1, buffer, len);
2633a253caaSDuncan Laurie
2643a253caaSDuncan Laurie i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
2653a253caaSDuncan Laurie
2663a253caaSDuncan Laurie /* Prepare for completion interrupt */
2673a253caaSDuncan Laurie tpm_cr50_i2c_enable_tpm_irq(chip);
2683a253caaSDuncan Laurie
2693a253caaSDuncan Laurie /* Send write request buffer with address */
2703a253caaSDuncan Laurie rc = tpm_cr50_i2c_transfer_message(&chip->dev, client->adapter, &msg);
2713a253caaSDuncan Laurie if (rc < 0)
2723a253caaSDuncan Laurie goto out;
2733a253caaSDuncan Laurie
2743a253caaSDuncan Laurie /* Wait for TPM to be ready, ignore timeout */
2753a253caaSDuncan Laurie tpm_cr50_i2c_wait_tpm_ready(chip);
2763a253caaSDuncan Laurie
2773a253caaSDuncan Laurie out:
2783a253caaSDuncan Laurie tpm_cr50_i2c_disable_tpm_irq(chip);
2793a253caaSDuncan Laurie i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
2803a253caaSDuncan Laurie
2813a253caaSDuncan Laurie if (rc < 0)
2823a253caaSDuncan Laurie return rc;
2833a253caaSDuncan Laurie
2843a253caaSDuncan Laurie return 0;
2853a253caaSDuncan Laurie }
2863a253caaSDuncan Laurie
2873a253caaSDuncan Laurie /**
2883a253caaSDuncan Laurie * tpm_cr50_check_locality() - Verify TPM locality 0 is active.
2893a253caaSDuncan Laurie * @chip: A TPM chip.
2903a253caaSDuncan Laurie *
2913a253caaSDuncan Laurie * Return:
2923a253caaSDuncan Laurie * - 0: Success.
2933a253caaSDuncan Laurie * - -errno: A POSIX error code.
2943a253caaSDuncan Laurie */
tpm_cr50_check_locality(struct tpm_chip * chip)2953a253caaSDuncan Laurie static int tpm_cr50_check_locality(struct tpm_chip *chip)
2963a253caaSDuncan Laurie {
2973a253caaSDuncan Laurie u8 mask = TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY;
2983a253caaSDuncan Laurie u8 buf;
2993a253caaSDuncan Laurie int rc;
3003a253caaSDuncan Laurie
3013a253caaSDuncan Laurie rc = tpm_cr50_i2c_read(chip, TPM_I2C_ACCESS(0), &buf, sizeof(buf));
3023a253caaSDuncan Laurie if (rc < 0)
3033a253caaSDuncan Laurie return rc;
3043a253caaSDuncan Laurie
3053a253caaSDuncan Laurie if ((buf & mask) == mask)
3063a253caaSDuncan Laurie return 0;
3073a253caaSDuncan Laurie
3083a253caaSDuncan Laurie return -EIO;
3093a253caaSDuncan Laurie }
3103a253caaSDuncan Laurie
3113a253caaSDuncan Laurie /**
3123a253caaSDuncan Laurie * tpm_cr50_release_locality() - Release TPM locality.
3133a253caaSDuncan Laurie * @chip: A TPM chip.
3143a253caaSDuncan Laurie * @force: Flag to force release if set.
3153a253caaSDuncan Laurie */
tpm_cr50_release_locality(struct tpm_chip * chip,bool force)3163a253caaSDuncan Laurie static void tpm_cr50_release_locality(struct tpm_chip *chip, bool force)
3173a253caaSDuncan Laurie {
3183a253caaSDuncan Laurie u8 mask = TPM_ACCESS_VALID | TPM_ACCESS_REQUEST_PENDING;
3193a253caaSDuncan Laurie u8 addr = TPM_I2C_ACCESS(0);
3203a253caaSDuncan Laurie u8 buf;
3213a253caaSDuncan Laurie
3223a253caaSDuncan Laurie if (tpm_cr50_i2c_read(chip, addr, &buf, sizeof(buf)) < 0)
3233a253caaSDuncan Laurie return;
3243a253caaSDuncan Laurie
3253a253caaSDuncan Laurie if (force || (buf & mask) == mask) {
3263a253caaSDuncan Laurie buf = TPM_ACCESS_ACTIVE_LOCALITY;
3273a253caaSDuncan Laurie tpm_cr50_i2c_write(chip, addr, &buf, sizeof(buf));
3283a253caaSDuncan Laurie }
3293a253caaSDuncan Laurie }
3303a253caaSDuncan Laurie
3313a253caaSDuncan Laurie /**
3323a253caaSDuncan Laurie * tpm_cr50_request_locality() - Request TPM locality 0.
3333a253caaSDuncan Laurie * @chip: A TPM chip.
3343a253caaSDuncan Laurie *
3353a253caaSDuncan Laurie * Return:
3363a253caaSDuncan Laurie * - 0: Success.
3373a253caaSDuncan Laurie * - -errno: A POSIX error code.
3383a253caaSDuncan Laurie */
tpm_cr50_request_locality(struct tpm_chip * chip)3393a253caaSDuncan Laurie static int tpm_cr50_request_locality(struct tpm_chip *chip)
3403a253caaSDuncan Laurie {
3413a253caaSDuncan Laurie u8 buf = TPM_ACCESS_REQUEST_USE;
3423a253caaSDuncan Laurie unsigned long stop;
3433a253caaSDuncan Laurie int rc;
3443a253caaSDuncan Laurie
3453a253caaSDuncan Laurie if (!tpm_cr50_check_locality(chip))
3463a253caaSDuncan Laurie return 0;
3473a253caaSDuncan Laurie
3483a253caaSDuncan Laurie rc = tpm_cr50_i2c_write(chip, TPM_I2C_ACCESS(0), &buf, sizeof(buf));
3493a253caaSDuncan Laurie if (rc < 0)
3503a253caaSDuncan Laurie return rc;
3513a253caaSDuncan Laurie
3523a253caaSDuncan Laurie stop = jiffies + chip->timeout_a;
3533a253caaSDuncan Laurie do {
3543a253caaSDuncan Laurie if (!tpm_cr50_check_locality(chip))
3553a253caaSDuncan Laurie return 0;
3563a253caaSDuncan Laurie
3573a253caaSDuncan Laurie msleep(TPM_CR50_TIMEOUT_SHORT_MS);
3583a253caaSDuncan Laurie } while (time_before(jiffies, stop));
3593a253caaSDuncan Laurie
3603a253caaSDuncan Laurie return -ETIMEDOUT;
3613a253caaSDuncan Laurie }
3623a253caaSDuncan Laurie
3633a253caaSDuncan Laurie /**
3643a253caaSDuncan Laurie * tpm_cr50_i2c_tis_status() - Read cr50 tis status.
3653a253caaSDuncan Laurie * @chip: A TPM chip.
3663a253caaSDuncan Laurie *
3673a253caaSDuncan Laurie * cr50 requires all 4 bytes of status register to be read.
3683a253caaSDuncan Laurie *
3693a253caaSDuncan Laurie * Return:
3703a253caaSDuncan Laurie * TPM status byte.
3713a253caaSDuncan Laurie */
tpm_cr50_i2c_tis_status(struct tpm_chip * chip)3723a253caaSDuncan Laurie static u8 tpm_cr50_i2c_tis_status(struct tpm_chip *chip)
3733a253caaSDuncan Laurie {
3743a253caaSDuncan Laurie u8 buf[4];
3753a253caaSDuncan Laurie
3763a253caaSDuncan Laurie if (tpm_cr50_i2c_read(chip, TPM_I2C_STS(0), buf, sizeof(buf)) < 0)
3773a253caaSDuncan Laurie return 0;
3783a253caaSDuncan Laurie
3793a253caaSDuncan Laurie return buf[0];
3803a253caaSDuncan Laurie }
3813a253caaSDuncan Laurie
3823a253caaSDuncan Laurie /**
3833a253caaSDuncan Laurie * tpm_cr50_i2c_tis_set_ready() - Set status register to ready.
3843a253caaSDuncan Laurie * @chip: A TPM chip.
3853a253caaSDuncan Laurie *
3863a253caaSDuncan Laurie * cr50 requires all 4 bytes of status register to be written.
3873a253caaSDuncan Laurie */
tpm_cr50_i2c_tis_set_ready(struct tpm_chip * chip)3883a253caaSDuncan Laurie static void tpm_cr50_i2c_tis_set_ready(struct tpm_chip *chip)
3893a253caaSDuncan Laurie {
3903a253caaSDuncan Laurie u8 buf[4] = { TPM_STS_COMMAND_READY };
3913a253caaSDuncan Laurie
3923a253caaSDuncan Laurie tpm_cr50_i2c_write(chip, TPM_I2C_STS(0), buf, sizeof(buf));
3933a253caaSDuncan Laurie msleep(TPM_CR50_TIMEOUT_SHORT_MS);
3943a253caaSDuncan Laurie }
3953a253caaSDuncan Laurie
3963a253caaSDuncan Laurie /**
3973a253caaSDuncan Laurie * tpm_cr50_i2c_get_burst_and_status() - Get burst count and status.
3983a253caaSDuncan Laurie * @chip: A TPM chip.
3993a253caaSDuncan Laurie * @mask: Status mask.
4003a253caaSDuncan Laurie * @burst: Return value for burst.
4013a253caaSDuncan Laurie * @status: Return value for status.
4023a253caaSDuncan Laurie *
4033a253caaSDuncan Laurie * cr50 uses bytes 3:2 of status register for burst count and
4043a253caaSDuncan Laurie * all 4 bytes must be read.
4053a253caaSDuncan Laurie *
4063a253caaSDuncan Laurie * Return:
4073a253caaSDuncan Laurie * - 0: Success.
4083a253caaSDuncan Laurie * - -errno: A POSIX error code.
4093a253caaSDuncan Laurie */
tpm_cr50_i2c_get_burst_and_status(struct tpm_chip * chip,u8 mask,size_t * burst,u32 * status)4103a253caaSDuncan Laurie static int tpm_cr50_i2c_get_burst_and_status(struct tpm_chip *chip, u8 mask,
4113a253caaSDuncan Laurie size_t *burst, u32 *status)
4123a253caaSDuncan Laurie {
4133a253caaSDuncan Laurie unsigned long stop;
4143a253caaSDuncan Laurie u8 buf[4];
4153a253caaSDuncan Laurie
4163a253caaSDuncan Laurie *status = 0;
4173a253caaSDuncan Laurie
4183a253caaSDuncan Laurie /* wait for burstcount */
4193a253caaSDuncan Laurie stop = jiffies + chip->timeout_b;
4203a253caaSDuncan Laurie
4213a253caaSDuncan Laurie do {
4223a253caaSDuncan Laurie if (tpm_cr50_i2c_read(chip, TPM_I2C_STS(0), buf, sizeof(buf)) < 0) {
4233a253caaSDuncan Laurie msleep(TPM_CR50_TIMEOUT_SHORT_MS);
4243a253caaSDuncan Laurie continue;
4253a253caaSDuncan Laurie }
4263a253caaSDuncan Laurie
4273a253caaSDuncan Laurie *status = *buf;
4283a253caaSDuncan Laurie *burst = le16_to_cpup((__le16 *)(buf + 1));
4293a253caaSDuncan Laurie
4303a253caaSDuncan Laurie if ((*status & mask) == mask &&
4313a253caaSDuncan Laurie *burst > 0 && *burst <= TPM_CR50_MAX_BUFSIZE - 1)
4323a253caaSDuncan Laurie return 0;
4333a253caaSDuncan Laurie
4343a253caaSDuncan Laurie msleep(TPM_CR50_TIMEOUT_SHORT_MS);
4353a253caaSDuncan Laurie } while (time_before(jiffies, stop));
4363a253caaSDuncan Laurie
4373a253caaSDuncan Laurie dev_err(&chip->dev, "Timeout reading burst and status\n");
4383a253caaSDuncan Laurie return -ETIMEDOUT;
4393a253caaSDuncan Laurie }
4403a253caaSDuncan Laurie
4413a253caaSDuncan Laurie /**
4423a253caaSDuncan Laurie * tpm_cr50_i2c_tis_recv() - TPM reception callback.
4433a253caaSDuncan Laurie * @chip: A TPM chip.
4443a253caaSDuncan Laurie * @buf: Reception buffer.
4453a253caaSDuncan Laurie * @buf_len: Buffer length to read.
4463a253caaSDuncan Laurie *
4473a253caaSDuncan Laurie * Return:
4483a253caaSDuncan Laurie * - >= 0: Number of read bytes.
4493a253caaSDuncan Laurie * - -errno: A POSIX error code.
4503a253caaSDuncan Laurie */
tpm_cr50_i2c_tis_recv(struct tpm_chip * chip,u8 * buf,size_t buf_len)4513a253caaSDuncan Laurie static int tpm_cr50_i2c_tis_recv(struct tpm_chip *chip, u8 *buf, size_t buf_len)
4523a253caaSDuncan Laurie {
4533a253caaSDuncan Laurie
4543a253caaSDuncan Laurie u8 mask = TPM_STS_VALID | TPM_STS_DATA_AVAIL;
4553a253caaSDuncan Laurie size_t burstcnt, cur, len, expected;
4563a253caaSDuncan Laurie u8 addr = TPM_I2C_DATA_FIFO(0);
4573a253caaSDuncan Laurie u32 status;
4583a253caaSDuncan Laurie int rc;
4593a253caaSDuncan Laurie
4603a253caaSDuncan Laurie if (buf_len < TPM_HEADER_SIZE)
4613a253caaSDuncan Laurie return -EINVAL;
4623a253caaSDuncan Laurie
4633a253caaSDuncan Laurie rc = tpm_cr50_i2c_get_burst_and_status(chip, mask, &burstcnt, &status);
4643a253caaSDuncan Laurie if (rc < 0)
4653a253caaSDuncan Laurie goto out_err;
4663a253caaSDuncan Laurie
4673a253caaSDuncan Laurie if (burstcnt > buf_len || burstcnt < TPM_HEADER_SIZE) {
4683a253caaSDuncan Laurie dev_err(&chip->dev,
4693a253caaSDuncan Laurie "Unexpected burstcnt: %zu (max=%zu, min=%d)\n",
4703a253caaSDuncan Laurie burstcnt, buf_len, TPM_HEADER_SIZE);
4713a253caaSDuncan Laurie rc = -EIO;
4723a253caaSDuncan Laurie goto out_err;
4733a253caaSDuncan Laurie }
4743a253caaSDuncan Laurie
4753a253caaSDuncan Laurie /* Read first chunk of burstcnt bytes */
4763a253caaSDuncan Laurie rc = tpm_cr50_i2c_read(chip, addr, buf, burstcnt);
4773a253caaSDuncan Laurie if (rc < 0) {
4783a253caaSDuncan Laurie dev_err(&chip->dev, "Read of first chunk failed\n");
4793a253caaSDuncan Laurie goto out_err;
4803a253caaSDuncan Laurie }
4813a253caaSDuncan Laurie
4823a253caaSDuncan Laurie /* Determine expected data in the return buffer */
4833a253caaSDuncan Laurie expected = be32_to_cpup((__be32 *)(buf + 2));
4843a253caaSDuncan Laurie if (expected > buf_len) {
4853a253caaSDuncan Laurie dev_err(&chip->dev, "Buffer too small to receive i2c data\n");
4863d785d73SZhihao Cheng rc = -E2BIG;
4873a253caaSDuncan Laurie goto out_err;
4883a253caaSDuncan Laurie }
4893a253caaSDuncan Laurie
4903a253caaSDuncan Laurie /* Now read the rest of the data */
4913a253caaSDuncan Laurie cur = burstcnt;
4923a253caaSDuncan Laurie while (cur < expected) {
4933a253caaSDuncan Laurie /* Read updated burst count and check status */
4943a253caaSDuncan Laurie rc = tpm_cr50_i2c_get_burst_and_status(chip, mask, &burstcnt, &status);
4953a253caaSDuncan Laurie if (rc < 0)
4963a253caaSDuncan Laurie goto out_err;
4973a253caaSDuncan Laurie
4983a253caaSDuncan Laurie len = min_t(size_t, burstcnt, expected - cur);
4993a253caaSDuncan Laurie rc = tpm_cr50_i2c_read(chip, addr, buf + cur, len);
5003a253caaSDuncan Laurie if (rc < 0) {
5013a253caaSDuncan Laurie dev_err(&chip->dev, "Read failed\n");
5023a253caaSDuncan Laurie goto out_err;
5033a253caaSDuncan Laurie }
5043a253caaSDuncan Laurie
5053a253caaSDuncan Laurie cur += len;
5063a253caaSDuncan Laurie }
5073a253caaSDuncan Laurie
5083a253caaSDuncan Laurie /* Ensure TPM is done reading data */
5093a253caaSDuncan Laurie rc = tpm_cr50_i2c_get_burst_and_status(chip, TPM_STS_VALID, &burstcnt, &status);
5103a253caaSDuncan Laurie if (rc < 0)
5113a253caaSDuncan Laurie goto out_err;
5123a253caaSDuncan Laurie if (status & TPM_STS_DATA_AVAIL) {
5133a253caaSDuncan Laurie dev_err(&chip->dev, "Data still available\n");
5143a253caaSDuncan Laurie rc = -EIO;
5153a253caaSDuncan Laurie goto out_err;
5163a253caaSDuncan Laurie }
5173a253caaSDuncan Laurie
5183a253caaSDuncan Laurie tpm_cr50_release_locality(chip, false);
5193a253caaSDuncan Laurie return cur;
5203a253caaSDuncan Laurie
5213a253caaSDuncan Laurie out_err:
5223a253caaSDuncan Laurie /* Abort current transaction if still pending */
5233a253caaSDuncan Laurie if (tpm_cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY)
5243a253caaSDuncan Laurie tpm_cr50_i2c_tis_set_ready(chip);
5253a253caaSDuncan Laurie
5263a253caaSDuncan Laurie tpm_cr50_release_locality(chip, false);
5273a253caaSDuncan Laurie return rc;
5283a253caaSDuncan Laurie }
5293a253caaSDuncan Laurie
5303a253caaSDuncan Laurie /**
5313a253caaSDuncan Laurie * tpm_cr50_i2c_tis_send() - TPM transmission callback.
5323a253caaSDuncan Laurie * @chip: A TPM chip.
5333a253caaSDuncan Laurie * @buf: Buffer to send.
5343a253caaSDuncan Laurie * @len: Buffer length.
5353a253caaSDuncan Laurie *
5363a253caaSDuncan Laurie * Return:
5373a253caaSDuncan Laurie * - 0: Success.
5383a253caaSDuncan Laurie * - -errno: A POSIX error code.
5393a253caaSDuncan Laurie */
tpm_cr50_i2c_tis_send(struct tpm_chip * chip,u8 * buf,size_t len)5403a253caaSDuncan Laurie static int tpm_cr50_i2c_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
5413a253caaSDuncan Laurie {
5423a253caaSDuncan Laurie size_t burstcnt, limit, sent = 0;
5433a253caaSDuncan Laurie u8 tpm_go[4] = { TPM_STS_GO };
5443a253caaSDuncan Laurie unsigned long stop;
5453a253caaSDuncan Laurie u32 status;
5463a253caaSDuncan Laurie int rc;
5473a253caaSDuncan Laurie
5483a253caaSDuncan Laurie rc = tpm_cr50_request_locality(chip);
5493a253caaSDuncan Laurie if (rc < 0)
5503a253caaSDuncan Laurie return rc;
5513a253caaSDuncan Laurie
5523a253caaSDuncan Laurie /* Wait until TPM is ready for a command */
5533a253caaSDuncan Laurie stop = jiffies + chip->timeout_b;
5543a253caaSDuncan Laurie while (!(tpm_cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY)) {
5553a253caaSDuncan Laurie if (time_after(jiffies, stop)) {
5563a253caaSDuncan Laurie rc = -ETIMEDOUT;
5573a253caaSDuncan Laurie goto out_err;
5583a253caaSDuncan Laurie }
5593a253caaSDuncan Laurie
5603a253caaSDuncan Laurie tpm_cr50_i2c_tis_set_ready(chip);
5613a253caaSDuncan Laurie }
5623a253caaSDuncan Laurie
5633a253caaSDuncan Laurie while (len > 0) {
5643a253caaSDuncan Laurie u8 mask = TPM_STS_VALID;
5653a253caaSDuncan Laurie
5663a253caaSDuncan Laurie /* Wait for data if this is not the first chunk */
5673a253caaSDuncan Laurie if (sent > 0)
5683a253caaSDuncan Laurie mask |= TPM_STS_DATA_EXPECT;
5693a253caaSDuncan Laurie
5703a253caaSDuncan Laurie /* Read burst count and check status */
5713a253caaSDuncan Laurie rc = tpm_cr50_i2c_get_burst_and_status(chip, mask, &burstcnt, &status);
5723a253caaSDuncan Laurie if (rc < 0)
5733a253caaSDuncan Laurie goto out_err;
5743a253caaSDuncan Laurie
5753a253caaSDuncan Laurie /*
5763a253caaSDuncan Laurie * Use burstcnt - 1 to account for the address byte
5773a253caaSDuncan Laurie * that is inserted by tpm_cr50_i2c_write()
5783a253caaSDuncan Laurie */
5793a253caaSDuncan Laurie limit = min_t(size_t, burstcnt - 1, len);
5803a253caaSDuncan Laurie rc = tpm_cr50_i2c_write(chip, TPM_I2C_DATA_FIFO(0), &buf[sent], limit);
5813a253caaSDuncan Laurie if (rc < 0) {
5823a253caaSDuncan Laurie dev_err(&chip->dev, "Write failed\n");
5833a253caaSDuncan Laurie goto out_err;
5843a253caaSDuncan Laurie }
5853a253caaSDuncan Laurie
5863a253caaSDuncan Laurie sent += limit;
5873a253caaSDuncan Laurie len -= limit;
5883a253caaSDuncan Laurie }
5893a253caaSDuncan Laurie
5903a253caaSDuncan Laurie /* Ensure TPM is not expecting more data */
5913a253caaSDuncan Laurie rc = tpm_cr50_i2c_get_burst_and_status(chip, TPM_STS_VALID, &burstcnt, &status);
5923a253caaSDuncan Laurie if (rc < 0)
5933a253caaSDuncan Laurie goto out_err;
5943a253caaSDuncan Laurie if (status & TPM_STS_DATA_EXPECT) {
5953a253caaSDuncan Laurie dev_err(&chip->dev, "Data still expected\n");
5963a253caaSDuncan Laurie rc = -EIO;
5973a253caaSDuncan Laurie goto out_err;
5983a253caaSDuncan Laurie }
5993a253caaSDuncan Laurie
6003a253caaSDuncan Laurie /* Start the TPM command */
6013a253caaSDuncan Laurie rc = tpm_cr50_i2c_write(chip, TPM_I2C_STS(0), tpm_go,
6023a253caaSDuncan Laurie sizeof(tpm_go));
6033a253caaSDuncan Laurie if (rc < 0) {
6043a253caaSDuncan Laurie dev_err(&chip->dev, "Start command failed\n");
6053a253caaSDuncan Laurie goto out_err;
6063a253caaSDuncan Laurie }
6073a253caaSDuncan Laurie return 0;
6083a253caaSDuncan Laurie
6093a253caaSDuncan Laurie out_err:
6103a253caaSDuncan Laurie /* Abort current transaction if still pending */
6113a253caaSDuncan Laurie if (tpm_cr50_i2c_tis_status(chip) & TPM_STS_COMMAND_READY)
6123a253caaSDuncan Laurie tpm_cr50_i2c_tis_set_ready(chip);
6133a253caaSDuncan Laurie
6143a253caaSDuncan Laurie tpm_cr50_release_locality(chip, false);
6153a253caaSDuncan Laurie return rc;
6163a253caaSDuncan Laurie }
6173a253caaSDuncan Laurie
6183a253caaSDuncan Laurie /**
6193a253caaSDuncan Laurie * tpm_cr50_i2c_req_canceled() - Callback to notify a request cancel.
6203a253caaSDuncan Laurie * @chip: A TPM chip.
6213a253caaSDuncan Laurie * @status: Status given by the cancel callback.
6223a253caaSDuncan Laurie *
6233a253caaSDuncan Laurie * Return:
6243a253caaSDuncan Laurie * True if command is ready, False otherwise.
6253a253caaSDuncan Laurie */
tpm_cr50_i2c_req_canceled(struct tpm_chip * chip,u8 status)6263a253caaSDuncan Laurie static bool tpm_cr50_i2c_req_canceled(struct tpm_chip *chip, u8 status)
6273a253caaSDuncan Laurie {
6283a253caaSDuncan Laurie return status == TPM_STS_COMMAND_READY;
6293a253caaSDuncan Laurie }
6303a253caaSDuncan Laurie
tpm_cr50_i2c_is_firmware_power_managed(struct device * dev)6315887d7f4SRob Barnes static bool tpm_cr50_i2c_is_firmware_power_managed(struct device *dev)
6325887d7f4SRob Barnes {
6335887d7f4SRob Barnes u8 val;
6345887d7f4SRob Barnes int ret;
6355887d7f4SRob Barnes
6365887d7f4SRob Barnes /* This flag should default true when the device property is not present */
6375887d7f4SRob Barnes ret = device_property_read_u8(dev, "firmware-power-managed", &val);
6385887d7f4SRob Barnes if (ret)
6395887d7f4SRob Barnes return true;
6405887d7f4SRob Barnes
6415887d7f4SRob Barnes return val;
6425887d7f4SRob Barnes }
6435887d7f4SRob Barnes
6443a253caaSDuncan Laurie static const struct tpm_class_ops cr50_i2c = {
6453a253caaSDuncan Laurie .flags = TPM_OPS_AUTO_STARTUP,
6463a253caaSDuncan Laurie .status = &tpm_cr50_i2c_tis_status,
6473a253caaSDuncan Laurie .recv = &tpm_cr50_i2c_tis_recv,
6483a253caaSDuncan Laurie .send = &tpm_cr50_i2c_tis_send,
6493a253caaSDuncan Laurie .cancel = &tpm_cr50_i2c_tis_set_ready,
6503a253caaSDuncan Laurie .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
6513a253caaSDuncan Laurie .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
6523a253caaSDuncan Laurie .req_canceled = &tpm_cr50_i2c_req_canceled,
6533a253caaSDuncan Laurie };
6543a253caaSDuncan Laurie
6553a253caaSDuncan Laurie #ifdef CONFIG_ACPI
6563a253caaSDuncan Laurie static const struct acpi_device_id cr50_i2c_acpi_id[] = {
6573a253caaSDuncan Laurie { "GOOG0005", 0 },
6583a253caaSDuncan Laurie {}
6593a253caaSDuncan Laurie };
6603a253caaSDuncan Laurie MODULE_DEVICE_TABLE(acpi, cr50_i2c_acpi_id);
6613a253caaSDuncan Laurie #endif
6623a253caaSDuncan Laurie
6633a253caaSDuncan Laurie #ifdef CONFIG_OF
6643a253caaSDuncan Laurie static const struct of_device_id of_cr50_i2c_match[] = {
6653a253caaSDuncan Laurie { .compatible = "google,cr50", },
6663a253caaSDuncan Laurie {}
6673a253caaSDuncan Laurie };
6683a253caaSDuncan Laurie MODULE_DEVICE_TABLE(of, of_cr50_i2c_match);
6693a253caaSDuncan Laurie #endif
6703a253caaSDuncan Laurie
6713a253caaSDuncan Laurie /**
6723a253caaSDuncan Laurie * tpm_cr50_i2c_probe() - Driver probe function.
6733a253caaSDuncan Laurie * @client: I2C client information.
6743a253caaSDuncan Laurie * @id: I2C device id.
6753a253caaSDuncan Laurie *
6763a253caaSDuncan Laurie * Return:
6773a253caaSDuncan Laurie * - 0: Success.
6783a253caaSDuncan Laurie * - -errno: A POSIX error code.
6793a253caaSDuncan Laurie */
tpm_cr50_i2c_probe(struct i2c_client * client)6806824f855SAdrian Ratiu static int tpm_cr50_i2c_probe(struct i2c_client *client)
6813a253caaSDuncan Laurie {
6823a253caaSDuncan Laurie struct tpm_i2c_cr50_priv_data *priv;
6833a253caaSDuncan Laurie struct device *dev = &client->dev;
6843a253caaSDuncan Laurie struct tpm_chip *chip;
6853a253caaSDuncan Laurie u32 vendor;
6863a253caaSDuncan Laurie u8 buf[4];
6873a253caaSDuncan Laurie int rc;
6883a253caaSDuncan Laurie
6893a253caaSDuncan Laurie if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
6903a253caaSDuncan Laurie return -ENODEV;
6913a253caaSDuncan Laurie
6923a253caaSDuncan Laurie chip = tpmm_chip_alloc(dev, &cr50_i2c);
6933a253caaSDuncan Laurie if (IS_ERR(chip))
6943a253caaSDuncan Laurie return PTR_ERR(chip);
6953a253caaSDuncan Laurie
6963a253caaSDuncan Laurie priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
6973a253caaSDuncan Laurie if (!priv)
6983a253caaSDuncan Laurie return -ENOMEM;
6993a253caaSDuncan Laurie
7003a253caaSDuncan Laurie /* cr50 is a TPM 2.0 chip */
7013a253caaSDuncan Laurie chip->flags |= TPM_CHIP_FLAG_TPM2;
7025887d7f4SRob Barnes if (tpm_cr50_i2c_is_firmware_power_managed(dev))
7033a253caaSDuncan Laurie chip->flags |= TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED;
7043a253caaSDuncan Laurie
7053a253caaSDuncan Laurie /* Default timeouts */
7063a253caaSDuncan Laurie chip->timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
7073a253caaSDuncan Laurie chip->timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
7083a253caaSDuncan Laurie chip->timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
7093a253caaSDuncan Laurie chip->timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
7103a253caaSDuncan Laurie
7113a253caaSDuncan Laurie dev_set_drvdata(&chip->dev, priv);
7123a253caaSDuncan Laurie init_completion(&priv->tpm_ready);
7133a253caaSDuncan Laurie
7143a253caaSDuncan Laurie if (client->irq > 0) {
7153a253caaSDuncan Laurie rc = devm_request_irq(dev, client->irq, tpm_cr50_i2c_int_handler,
716446cd6f0STian Tao IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
717446cd6f0STian Tao IRQF_NO_AUTOEN,
7183a253caaSDuncan Laurie dev->driver->name, chip);
7193a253caaSDuncan Laurie if (rc < 0) {
7203a253caaSDuncan Laurie dev_err(dev, "Failed to probe IRQ %d\n", client->irq);
7213a253caaSDuncan Laurie return rc;
7223a253caaSDuncan Laurie }
7233a253caaSDuncan Laurie
7243a253caaSDuncan Laurie priv->irq = client->irq;
7253a253caaSDuncan Laurie } else {
7263a253caaSDuncan Laurie dev_warn(dev, "No IRQ, will use %ums delay for TPM ready\n",
7273a253caaSDuncan Laurie TPM_CR50_TIMEOUT_NOIRQ_MS);
7283a253caaSDuncan Laurie }
7293a253caaSDuncan Laurie
7303a253caaSDuncan Laurie rc = tpm_cr50_request_locality(chip);
7313a253caaSDuncan Laurie if (rc < 0) {
7323a253caaSDuncan Laurie dev_err(dev, "Could not request locality\n");
7333a253caaSDuncan Laurie return rc;
7343a253caaSDuncan Laurie }
7353a253caaSDuncan Laurie
7363a253caaSDuncan Laurie /* Read four bytes from DID_VID register */
7373a253caaSDuncan Laurie rc = tpm_cr50_i2c_read(chip, TPM_I2C_DID_VID(0), buf, sizeof(buf));
7383a253caaSDuncan Laurie if (rc < 0) {
7393a253caaSDuncan Laurie dev_err(dev, "Could not read vendor id\n");
7403a253caaSDuncan Laurie tpm_cr50_release_locality(chip, true);
7413a253caaSDuncan Laurie return rc;
7423a253caaSDuncan Laurie }
7433a253caaSDuncan Laurie
7443a253caaSDuncan Laurie vendor = le32_to_cpup((__le32 *)buf);
7459c438fdeSJes B. Klinke if (vendor != TPM_CR50_I2C_DID_VID && vendor != TPM_TI50_I2C_DID_VID) {
7463a253caaSDuncan Laurie dev_err(dev, "Vendor ID did not match! ID was %08x\n", vendor);
7473a253caaSDuncan Laurie tpm_cr50_release_locality(chip, true);
7483a253caaSDuncan Laurie return -ENODEV;
7493a253caaSDuncan Laurie }
7503a253caaSDuncan Laurie
7519c438fdeSJes B. Klinke dev_info(dev, "%s TPM 2.0 (i2c 0x%02x irq %d id 0x%x)\n",
7529c438fdeSJes B. Klinke vendor == TPM_TI50_I2C_DID_VID ? "ti50" : "cr50",
7533a253caaSDuncan Laurie client->addr, client->irq, vendor >> 16);
7543a253caaSDuncan Laurie return tpm_chip_register(chip);
7553a253caaSDuncan Laurie }
7563a253caaSDuncan Laurie
7573a253caaSDuncan Laurie /**
7583a253caaSDuncan Laurie * tpm_cr50_i2c_remove() - Driver remove function.
7593a253caaSDuncan Laurie * @client: I2C client information.
7603a253caaSDuncan Laurie *
7613a253caaSDuncan Laurie * Return:
7623a253caaSDuncan Laurie * - 0: Success.
7633a253caaSDuncan Laurie * - -errno: A POSIX error code.
7643a253caaSDuncan Laurie */
tpm_cr50_i2c_remove(struct i2c_client * client)765ed5c2f5fSUwe Kleine-König static void tpm_cr50_i2c_remove(struct i2c_client *client)
7663a253caaSDuncan Laurie {
7673a253caaSDuncan Laurie struct tpm_chip *chip = i2c_get_clientdata(client);
7683a253caaSDuncan Laurie struct device *dev = &client->dev;
7693a253caaSDuncan Laurie
7703a253caaSDuncan Laurie if (!chip) {
771e0687fe9SUwe Kleine-König dev_crit(dev, "Could not get client data at remove, memory corruption ahead\n");
772ed5c2f5fSUwe Kleine-König return;
7733a253caaSDuncan Laurie }
7743a253caaSDuncan Laurie
7753a253caaSDuncan Laurie tpm_chip_unregister(chip);
7763a253caaSDuncan Laurie tpm_cr50_release_locality(chip, true);
7773a253caaSDuncan Laurie }
7783a253caaSDuncan Laurie
7793a253caaSDuncan Laurie static SIMPLE_DEV_PM_OPS(cr50_i2c_pm, tpm_pm_suspend, tpm_pm_resume);
7803a253caaSDuncan Laurie
7813a253caaSDuncan Laurie static struct i2c_driver cr50_i2c_driver = {
782*be6f48a7SUwe Kleine-König .probe = tpm_cr50_i2c_probe,
7833a253caaSDuncan Laurie .remove = tpm_cr50_i2c_remove,
7843a253caaSDuncan Laurie .driver = {
7853a253caaSDuncan Laurie .name = "cr50_i2c",
7863a253caaSDuncan Laurie .pm = &cr50_i2c_pm,
7873a253caaSDuncan Laurie .acpi_match_table = ACPI_PTR(cr50_i2c_acpi_id),
7883a253caaSDuncan Laurie .of_match_table = of_match_ptr(of_cr50_i2c_match),
7893a253caaSDuncan Laurie },
7903a253caaSDuncan Laurie };
7913a253caaSDuncan Laurie
7923a253caaSDuncan Laurie module_i2c_driver(cr50_i2c_driver);
7933a253caaSDuncan Laurie
7943a253caaSDuncan Laurie MODULE_DESCRIPTION("cr50 TPM I2C Driver");
7953a253caaSDuncan Laurie MODULE_LICENSE("GPL");
796