1aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe/* 2c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe * Copyright (C) 2012,2013 Infineon Technologies 3aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * 4aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * Authors: 5aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * Peter Huewe <peter.huewe@infineon.com> 6aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * 7aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * Device driver for TCG/TCPA TPM (trusted platform module). 8aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * Specifications at www.trustedcomputinggroup.org 9aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * 10aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * This device driver implements the TPM interface as defined in 11aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * the TCG TPM Interface Spec version 1.2, revision 1.0 and the 12aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * Infineon I2C Protocol Stack Specification v0.20. 13aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * 14aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * It is based on the original tpm_tis device driver from Leendert van 15aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * Dorn and Kyleen Hall. 16aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * 17aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * This program is free software; you can redistribute it and/or 18aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * modify it under the terms of the GNU General Public License as 19aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * published by the Free Software Foundation, version 2 of the 20aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * License. 21aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * 22aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * 23aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe */ 24aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#include <linux/i2c.h> 25aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#include <linux/module.h> 26aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#include <linux/wait.h> 27aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#include "tpm.h" 28aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 29aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe/* max. buffer size supported by our TPM */ 30aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#define TPM_BUFSIZE 1260 31aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 32aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe/* max. number of iterations after I2C NAK */ 33aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#define MAX_COUNT 3 34aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 35aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#define SLEEP_DURATION_LOW 55 36aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#define SLEEP_DURATION_HI 65 37aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 38aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe/* max. number of iterations after I2C NAK for 'long' commands 39aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * we need this especially for sending TPM_READY, since the cleanup after the 40aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * transtion to the ready state may take some time, but it is unpredictable 41aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * how long it will take. 42aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe */ 43aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#define MAX_COUNT_LONG 50 44aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 45aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#define SLEEP_DURATION_LONG_LOW 200 46aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#define SLEEP_DURATION_LONG_HI 220 47aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 48aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe/* After sending TPM_READY to 'reset' the TPM we have to sleep even longer */ 49aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#define SLEEP_DURATION_RESET_LOW 2400 50aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#define SLEEP_DURATION_RESET_HI 2600 51aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 52aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe/* we want to use usleep_range instead of msleep for the 5ms TPM_TIMEOUT */ 53aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#define TPM_TIMEOUT_US_LOW (TPM_TIMEOUT * 1000) 54aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#define TPM_TIMEOUT_US_HI (TPM_TIMEOUT_US_LOW + 2000) 55aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 56aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe/* expected value for DIDVID register */ 57c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe#define TPM_TIS_I2C_DID_VID_9635 0xd1150b00L 58c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe#define TPM_TIS_I2C_DID_VID_9645 0x001a15d1L 59c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe 60c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Hueweenum i2c_chip_type { 61c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe SLB9635, 62c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe SLB9645, 63c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe UNKNOWN, 64c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe}; 65aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 66aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe/* Structure to store I2C TPM specific stuff */ 67aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestruct tpm_inf_dev { 68aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe struct i2c_client *client; 69aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */ 70aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe struct tpm_chip *chip; 71c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe enum i2c_chip_type chip_type; 72aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe}; 73aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 74aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic struct tpm_inf_dev tpm_dev; 75aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 76aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe/* 77aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * iic_tpm_read() - read from TPM register 78aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * @addr: register address to read from 79aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * @buffer: provided by caller 80aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * @len: number of bytes to read 81aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * 82aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * Read len bytes from TPM register and put them into 83aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * buffer (little-endian format, i.e. first byte is put into buffer[0]). 84aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * 85aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * NOTE: TPM is big-endian for multi-byte values. Multi-byte 86aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * values have to be swapped. 87aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * 88aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * NOTE: We can't unfortunately use the combined read/write functions 89aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * provided by the i2c core as the TPM currently does not support the 90aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * repeated start condition and due to it's special requirements. 91aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * The i2c_smbus* functions do not work for this chip. 92aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * 93aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * Return -EIO on error, 0 on success. 94aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe */ 95aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic int iic_tpm_read(u8 addr, u8 *buffer, size_t len) 96aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe{ 97aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 98eef8b6291987c059dacb07dd516d4ada0e3362afShubhrajyoti Datta struct i2c_msg msg1 = { 99eef8b6291987c059dacb07dd516d4ada0e3362afShubhrajyoti Datta .addr = tpm_dev.client->addr, 100eef8b6291987c059dacb07dd516d4ada0e3362afShubhrajyoti Datta .len = 1, 101eef8b6291987c059dacb07dd516d4ada0e3362afShubhrajyoti Datta .buf = &addr 102eef8b6291987c059dacb07dd516d4ada0e3362afShubhrajyoti Datta }; 103eef8b6291987c059dacb07dd516d4ada0e3362afShubhrajyoti Datta struct i2c_msg msg2 = { 104eef8b6291987c059dacb07dd516d4ada0e3362afShubhrajyoti Datta .addr = tpm_dev.client->addr, 105eef8b6291987c059dacb07dd516d4ada0e3362afShubhrajyoti Datta .flags = I2C_M_RD, 106eef8b6291987c059dacb07dd516d4ada0e3362afShubhrajyoti Datta .len = len, 107eef8b6291987c059dacb07dd516d4ada0e3362afShubhrajyoti Datta .buf = buffer 108eef8b6291987c059dacb07dd516d4ada0e3362afShubhrajyoti Datta }; 109c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe struct i2c_msg msgs[] = {msg1, msg2}; 110aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 111c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe int rc = 0; 112aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe int count; 113aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 114aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* Lock the adapter for the duration of the whole sequence. */ 115aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (!tpm_dev.client->adapter->algo->master_xfer) 116aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return -EOPNOTSUPP; 117aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe i2c_lock_adapter(tpm_dev.client->adapter); 118aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 119c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe if (tpm_dev.chip_type == SLB9645) { 120c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe /* use a combined read for newer chips 121c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe * unfortunately the smbus functions are not suitable due to 122c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe * the 32 byte limit of the smbus. 123c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe * retries should usually not be needed, but are kept just to 124c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe * be on the safe side. 125c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe */ 126c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe for (count = 0; count < MAX_COUNT; count++) { 127c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe rc = __i2c_transfer(tpm_dev.client->adapter, msgs, 2); 128c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe if (rc > 0) 129c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe break; /* break here to skip sleep */ 130c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); 131c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe } 132c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe } else { 133c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe /* slb9635 protocol should work in all cases */ 134c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe for (count = 0; count < MAX_COUNT; count++) { 135c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); 136c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe if (rc > 0) 137c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe break; /* break here to skip sleep */ 138c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe 139c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); 140c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe } 141aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 142c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe if (rc <= 0) 143c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe goto out; 144c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe 145c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe /* After the TPM has successfully received the register address 146c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe * it needs some time, thus we're sleeping here again, before 147c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe * retrieving the data 148c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe */ 149c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe for (count = 0; count < MAX_COUNT; count++) { 150c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); 151c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe rc = __i2c_transfer(tpm_dev.client->adapter, &msg2, 1); 152c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe if (rc > 0) 153c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe break; 154c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe } 155aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 156aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 157aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Hueweout: 158aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe i2c_unlock_adapter(tpm_dev.client->adapter); 159c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe /* take care of 'guard time' */ 160c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); 161c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe 1626aa4ef4dab92fc8d4f0e5ea735ae3fd520af510bPeter Huewe /* __i2c_transfer returns the number of successfully transferred 1636aa4ef4dab92fc8d4f0e5ea735ae3fd520af510bPeter Huewe * messages. 1646aa4ef4dab92fc8d4f0e5ea735ae3fd520af510bPeter Huewe * So rc should be greater than 0 here otherwise we have an error. 1656aa4ef4dab92fc8d4f0e5ea735ae3fd520af510bPeter Huewe */ 166aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (rc <= 0) 167aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return -EIO; 168aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 169aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return 0; 170aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe} 171aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 172aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, 173aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe unsigned int sleep_low, 174aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe unsigned int sleep_hi, u8 max_count) 175aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe{ 176aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe int rc = -EIO; 177aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe int count; 178aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 179eef8b6291987c059dacb07dd516d4ada0e3362afShubhrajyoti Datta struct i2c_msg msg1 = { 180eef8b6291987c059dacb07dd516d4ada0e3362afShubhrajyoti Datta .addr = tpm_dev.client->addr, 181eef8b6291987c059dacb07dd516d4ada0e3362afShubhrajyoti Datta .len = len + 1, 182eef8b6291987c059dacb07dd516d4ada0e3362afShubhrajyoti Datta .buf = tpm_dev.buf 183eef8b6291987c059dacb07dd516d4ada0e3362afShubhrajyoti Datta }; 184aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 185aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (len > TPM_BUFSIZE) 186aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return -EINVAL; 187aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 188aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (!tpm_dev.client->adapter->algo->master_xfer) 189aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return -EOPNOTSUPP; 190aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe i2c_lock_adapter(tpm_dev.client->adapter); 191aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 192aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* prepend the 'register address' to the buffer */ 193aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe tpm_dev.buf[0] = addr; 194aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe memcpy(&(tpm_dev.buf[1]), buffer, len); 195aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 196aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* 197aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * NOTE: We have to use these special mechanisms here and unfortunately 198aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * cannot rely on the standard behavior of i2c_transfer. 199c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe * Even for newer chips the smbus functions are not 200c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe * suitable due to the 32 byte limit of the smbus. 201aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe */ 202aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe for (count = 0; count < max_count; count++) { 203aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); 204aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (rc > 0) 205aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe break; 206aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe usleep_range(sleep_low, sleep_hi); 207aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 208aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 209aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe i2c_unlock_adapter(tpm_dev.client->adapter); 210c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe /* take care of 'guard time' */ 211c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); 2126aa4ef4dab92fc8d4f0e5ea735ae3fd520af510bPeter Huewe 2136aa4ef4dab92fc8d4f0e5ea735ae3fd520af510bPeter Huewe /* __i2c_transfer returns the number of successfully transferred 2146aa4ef4dab92fc8d4f0e5ea735ae3fd520af510bPeter Huewe * messages. 2156aa4ef4dab92fc8d4f0e5ea735ae3fd520af510bPeter Huewe * So rc should be greater than 0 here otherwise we have an error. 2166aa4ef4dab92fc8d4f0e5ea735ae3fd520af510bPeter Huewe */ 217aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (rc <= 0) 218aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return -EIO; 219aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 220aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return 0; 221aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe} 222aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 223aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe/* 224aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * iic_tpm_write() - write to TPM register 225aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * @addr: register address to write to 226aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * @buffer: containing data to be written 227aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * @len: number of bytes to write 228aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * 229aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * Write len bytes from provided buffer to TPM register (little 230aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * endian format, i.e. buffer[0] is written as first byte). 231aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * 232aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * NOTE: TPM is big-endian for multi-byte values. Multi-byte 233aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * values have to be swapped. 234aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * 235aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * NOTE: use this function instead of the iic_tpm_write_generic function. 236aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * 237aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * Return -EIO on error, 0 on success 238aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe */ 239aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic int iic_tpm_write(u8 addr, u8 *buffer, size_t len) 240aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe{ 241aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LOW, 242aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe SLEEP_DURATION_HI, MAX_COUNT); 243aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe} 244aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 245aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe/* 246aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * This function is needed especially for the cleanup situation after 247aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * sending TPM_READY 248aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * */ 249aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic int iic_tpm_write_long(u8 addr, u8 *buffer, size_t len) 250aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe{ 251aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LONG_LOW, 252aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe SLEEP_DURATION_LONG_HI, MAX_COUNT_LONG); 253aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe} 254aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 255aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Hueweenum tis_access { 256aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe TPM_ACCESS_VALID = 0x80, 257aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe TPM_ACCESS_ACTIVE_LOCALITY = 0x20, 258aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe TPM_ACCESS_REQUEST_PENDING = 0x04, 259aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe TPM_ACCESS_REQUEST_USE = 0x02, 260aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe}; 261aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 262aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Hueweenum tis_status { 263aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe TPM_STS_VALID = 0x80, 264aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe TPM_STS_COMMAND_READY = 0x40, 265aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe TPM_STS_GO = 0x20, 266aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe TPM_STS_DATA_AVAIL = 0x10, 267aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe TPM_STS_DATA_EXPECT = 0x08, 268aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe}; 269aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 270aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Hueweenum tis_defaults { 271aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe TIS_SHORT_TIMEOUT = 750, /* ms */ 272aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe TIS_LONG_TIMEOUT = 2000, /* 2 sec */ 273aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe}; 274aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 275aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#define TPM_ACCESS(l) (0x0000 | ((l) << 4)) 276aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#define TPM_STS(l) (0x0001 | ((l) << 4)) 277aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4)) 278aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe#define TPM_DID_VID(l) (0x0006 | ((l) << 4)) 279aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 280aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic int check_locality(struct tpm_chip *chip, int loc) 281aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe{ 282aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe u8 buf; 283aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe int rc; 284aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 285aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe rc = iic_tpm_read(TPM_ACCESS(loc), &buf, 1); 286aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (rc < 0) 287aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return rc; 288aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 289aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == 290aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { 291aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe chip->vendor.locality = loc; 292aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return loc; 293aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 294aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 295aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return -EIO; 296aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe} 297aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 298aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe/* implementation similar to tpm_tis */ 299aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic void release_locality(struct tpm_chip *chip, int loc, int force) 300aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe{ 301aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe u8 buf; 302aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0) 303aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return; 304aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 305aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (force || (buf & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == 306aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) { 307aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe buf = TPM_ACCESS_ACTIVE_LOCALITY; 308aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe iic_tpm_write(TPM_ACCESS(loc), &buf, 1); 309aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 310aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe} 311aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 312aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic int request_locality(struct tpm_chip *chip, int loc) 313aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe{ 314aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe unsigned long stop; 315aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe u8 buf = TPM_ACCESS_REQUEST_USE; 316aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 317aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (check_locality(chip, loc) >= 0) 318aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return loc; 319aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 320aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe iic_tpm_write(TPM_ACCESS(loc), &buf, 1); 321aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 322aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* wait for burstcount */ 323aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe stop = jiffies + chip->vendor.timeout_a; 324aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe do { 325aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (check_locality(chip, loc) >= 0) 326aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return loc; 327aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI); 328aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } while (time_before(jiffies, stop)); 329aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 330aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return -ETIME; 331aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe} 332aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 333aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic u8 tpm_tis_i2c_status(struct tpm_chip *chip) 334aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe{ 335aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* NOTE: since I2C read may fail, return 0 in this case --> time-out */ 336c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe u8 buf = 0xFF; 337c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe u8 i = 0; 338c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe 339c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe do { 340c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0) 341c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe return 0; 342c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe 343c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe i++; 344c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe /* if locallity is set STS should not be 0xFF */ 345c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe } while ((buf == 0xFF) && i < 10); 346c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe 347c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe return buf; 348aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe} 349aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 350aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic void tpm_tis_i2c_ready(struct tpm_chip *chip) 351aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe{ 352aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* this causes the current command to be aborted */ 353aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe u8 buf = TPM_STS_COMMAND_READY; 354aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1); 355aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe} 356aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 357aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic ssize_t get_burstcount(struct tpm_chip *chip) 358aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe{ 359aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe unsigned long stop; 360aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe ssize_t burstcnt; 361aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe u8 buf[3]; 362aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 363aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* wait for burstcount */ 364aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* which timeout value, spec has 2 answers (c & d) */ 365aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe stop = jiffies + chip->vendor.timeout_d; 366aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe do { 367aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* Note: STS is little endian */ 368aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (iic_tpm_read(TPM_STS(chip->vendor.locality)+1, buf, 3) < 0) 369aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe burstcnt = 0; 370aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe else 371aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0]; 372aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 373aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (burstcnt) 374aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return burstcnt; 375aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 376aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI); 377aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } while (time_before(jiffies, stop)); 378aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return -EBUSY; 379aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe} 380aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 381aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, 382aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe int *status) 383aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe{ 384aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe unsigned long stop; 385aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 386aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* check current status */ 387aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe *status = tpm_tis_i2c_status(chip); 388c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe if ((*status != 0xFF) && (*status & mask) == mask) 389aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return 0; 390aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 391aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe stop = jiffies + timeout; 392aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe do { 393aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* since we just checked the status, give the TPM some time */ 394aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI); 395aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe *status = tpm_tis_i2c_status(chip); 396aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if ((*status & mask) == mask) 397aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return 0; 398aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 399aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } while (time_before(jiffies, stop)); 400aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 401aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return -ETIME; 402aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe} 403aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 404aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) 405aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe{ 406aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe size_t size = 0; 407aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe ssize_t burstcnt; 408aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe u8 retries = 0; 409aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe int rc; 410aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 411aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe while (size < count) { 412aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe burstcnt = get_burstcount(chip); 413aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 414aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* burstcnt < 0 = TPM is busy */ 415aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (burstcnt < 0) 416aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return burstcnt; 417aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 418aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* limit received data to max. left */ 419aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (burstcnt > (count - size)) 420aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe burstcnt = count - size; 421aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 422aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality), 423aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe &(buf[size]), burstcnt); 424aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (rc == 0) 425aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe size += burstcnt; 426aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe else if (rc < 0) 427aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe retries++; 428aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 429aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* avoid endless loop in case of broken HW */ 430aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (retries > MAX_COUNT_LONG) 431aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return -EIO; 432aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 433aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return size; 434aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe} 435aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 436aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) 437aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe{ 438aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe int size = 0; 439aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe int expected, status; 440aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 441aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (count < TPM_HEADER_SIZE) { 442aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe size = -EIO; 443aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe goto out; 444aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 445aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 446aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* read first 10 bytes, including tag, paramsize, and result */ 447aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe size = recv_data(chip, buf, TPM_HEADER_SIZE); 448aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (size < TPM_HEADER_SIZE) { 449aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe dev_err(chip->dev, "Unable to read header\n"); 450aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe goto out; 451aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 452aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 453aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe expected = be32_to_cpu(*(__be32 *)(buf + 2)); 454aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if ((size_t) expected > count) { 455aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe size = -EIO; 456aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe goto out; 457aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 458aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 459aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe size += recv_data(chip, &buf[TPM_HEADER_SIZE], 460aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe expected - TPM_HEADER_SIZE); 461aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (size < expected) { 462aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe dev_err(chip->dev, "Unable to read remainder of result\n"); 463aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe size = -ETIME; 464aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe goto out; 465aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 466aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 467aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); 468aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (status & TPM_STS_DATA_AVAIL) { /* retry? */ 469aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe dev_err(chip->dev, "Error left over data\n"); 470aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe size = -EIO; 471aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe goto out; 472aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 473aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 474aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Hueweout: 475aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe tpm_tis_i2c_ready(chip); 476aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* The TPM needs some time to clean up here, 477aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * so we sleep rather than keeping the bus busy 478aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe */ 479aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI); 480aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe release_locality(chip, chip->vendor.locality, 0); 481aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return size; 482aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe} 483aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 484aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) 485aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe{ 486aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe int rc, status; 487aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe ssize_t burstcnt; 488aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe size_t count = 0; 489aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe u8 retries = 0; 490aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe u8 sts = TPM_STS_GO; 491aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 492aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (len > TPM_BUFSIZE) 493aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return -E2BIG; /* command is too long for our tpm, sorry */ 494aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 495aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (request_locality(chip, 0) < 0) 496aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return -EBUSY; 497aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 498aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe status = tpm_tis_i2c_status(chip); 499aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if ((status & TPM_STS_COMMAND_READY) == 0) { 500aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe tpm_tis_i2c_ready(chip); 501aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (wait_for_stat 502aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe (chip, TPM_STS_COMMAND_READY, 503aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe chip->vendor.timeout_b, &status) < 0) { 504aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe rc = -ETIME; 505aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe goto out_err; 506aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 507aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 508aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 509aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe while (count < len - 1) { 510aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe burstcnt = get_burstcount(chip); 511aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 512aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* burstcnt < 0 = TPM is busy */ 513aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (burstcnt < 0) 514aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return burstcnt; 515aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 516aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (burstcnt > (len - 1 - count)) 517aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe burstcnt = len - 1 - count; 518aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 519aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), 520aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe &(buf[count]), burstcnt); 521aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (rc == 0) 522aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe count += burstcnt; 523aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe else if (rc < 0) 524aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe retries++; 525aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 526aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* avoid endless loop in case of broken HW */ 527aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (retries > MAX_COUNT_LONG) { 528aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe rc = -EIO; 529aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe goto out_err; 530aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 531aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 532aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe wait_for_stat(chip, TPM_STS_VALID, 533aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe chip->vendor.timeout_c, &status); 534aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 535aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if ((status & TPM_STS_DATA_EXPECT) == 0) { 536aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe rc = -EIO; 537aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe goto out_err; 538aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 539aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 540aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 541aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* write last byte */ 542aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1); 543aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); 544aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if ((status & TPM_STS_DATA_EXPECT) != 0) { 545aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe rc = -EIO; 546aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe goto out_err; 547aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 548aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 549aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* go and do it */ 550aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1); 551aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 552aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return len; 553aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Hueweout_err: 554aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe tpm_tis_i2c_ready(chip); 555aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* The TPM needs some time to clean up here, 556aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe * so we sleep rather than keeping the bus busy 557aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe */ 558aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI); 559aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe release_locality(chip, chip->vendor.locality, 0); 560aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return rc; 561aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe} 562aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 5631f866057291fc00f14e4962473bd7724ffa8f578Stefan Bergerstatic bool tpm_tis_i2c_req_canceled(struct tpm_chip *chip, u8 status) 5641f866057291fc00f14e4962473bd7724ffa8f578Stefan Berger{ 5651f866057291fc00f14e4962473bd7724ffa8f578Stefan Berger return (status == TPM_STS_COMMAND_READY); 5661f866057291fc00f14e4962473bd7724ffa8f578Stefan Berger} 5671f866057291fc00f14e4962473bd7724ffa8f578Stefan Berger 56801ad1fa75dd243909d62dba25a93254b20d5fe81Jason Gunthorpestatic const struct tpm_class_ops tpm_tis_i2c = { 569aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe .status = tpm_tis_i2c_status, 570aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe .recv = tpm_tis_i2c_recv, 571aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe .send = tpm_tis_i2c_send, 572aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe .cancel = tpm_tis_i2c_ready, 573aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, 574aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, 5751f866057291fc00f14e4962473bd7724ffa8f578Stefan Berger .req_canceled = tpm_tis_i2c_req_canceled, 576aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe}; 577aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 578afc6d36912f3f3404fcc1dd2234d9028706a9b6aBill Pembertonstatic int tpm_tis_i2c_init(struct device *dev) 579aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe{ 580aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe u32 vendor; 581aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe int rc = 0; 582aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe struct tpm_chip *chip; 583aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 584aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe chip = tpm_register_hardware(dev, &tpm_tis_i2c); 585aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (!chip) { 586c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe dev_err(dev, "could not register hardware\n"); 587aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe rc = -ENODEV; 588aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe goto out_err; 589aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 590aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 591aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* Disable interrupts */ 592aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe chip->vendor.irq = 0; 593aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 594aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* Default timeouts */ 595aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); 596aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); 597aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); 598aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); 599aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 600aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (request_locality(chip, 0) != 0) { 601c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe dev_err(dev, "could not request locality\n"); 602aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe rc = -ENODEV; 603aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe goto out_vendor; 604aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 605aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 606aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* read four bytes from DID_VID register */ 607aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (iic_tpm_read(TPM_DID_VID(0), (u8 *)&vendor, 4) < 0) { 608c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe dev_err(dev, "could not read vendor id\n"); 609aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe rc = -EIO; 610aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe goto out_release; 611aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 612aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 613c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe if (vendor == TPM_TIS_I2C_DID_VID_9645) { 614c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe tpm_dev.chip_type = SLB9645; 615c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe } else if (vendor == TPM_TIS_I2C_DID_VID_9635) { 616c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe tpm_dev.chip_type = SLB9635; 617c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe } else { 618c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe dev_err(dev, "vendor id did not match! ID was %08x\n", vendor); 619aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe rc = -ENODEV; 620aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe goto out_release; 621aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 622aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 623aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe dev_info(dev, "1.2 TPM (device-id 0x%X)\n", vendor >> 16); 624aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 625aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe INIT_LIST_HEAD(&chip->vendor.list); 626aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe tpm_dev.chip = chip; 627aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 628aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe tpm_get_timeouts(chip); 629aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe tpm_do_selftest(chip); 630aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 631aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return 0; 632aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 633aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Hueweout_release: 634aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe release_locality(chip, chip->vendor.locality, 1); 635aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 636aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Hueweout_vendor: 637aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* close file handles */ 638aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe tpm_dev_vendor_release(chip); 639aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 640aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* remove hardware */ 641aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe tpm_remove_hardware(chip->dev); 642aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 643aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* reset these pointers, otherwise we oops */ 644aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe chip->dev->release = NULL; 645aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe chip->release = NULL; 646aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe tpm_dev.client = NULL; 647aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Hueweout_err: 648aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return rc; 649aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe} 650aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 651aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic const struct i2c_device_id tpm_tis_i2c_table[] = { 652aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe {"tpm_i2c_infineon", 0}, 653c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe {"slb9635tt", 0}, 654c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe {"slb9645tt", 1}, 655aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe {}, 656aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe}; 657aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 658aad628c1d91a6db57e572e4c1f35e863d81061d7Peter HueweMODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table); 659c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe 660c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe#ifdef CONFIG_OF 661c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewestatic const struct of_device_id tpm_tis_i2c_of_match[] = { 66221dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe { 66321dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe .name = "tpm_i2c_infineon", 66421dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe .type = "tpm", 66521dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe .compatible = "infineon,tpm_i2c_infineon", 66621dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe .data = (void *)0 66721dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe }, 66821dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe { 66921dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe .name = "slb9635tt", 67021dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe .type = "tpm", 67121dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe .compatible = "infineon,slb9635tt", 67221dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe .data = (void *)0 67321dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe }, 67421dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe { 67521dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe .name = "slb9645tt", 67621dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe .type = "tpm", 67721dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe .compatible = "infineon,slb9645tt", 67821dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe .data = (void *)1 67921dc02eab989d260fd9e22b72a29ac139a727cddPeter Huewe }, 680c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe {}, 681c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe}; 682c61c86dd6e0a8037be73cf27212f389e46af60a4Peter HueweMODULE_DEVICE_TABLE(of, tpm_tis_i2c_of_match); 683c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe#endif 684c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe 685aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume); 686aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 687afc6d36912f3f3404fcc1dd2234d9028706a9b6aBill Pembertonstatic int tpm_tis_i2c_probe(struct i2c_client *client, 688aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe const struct i2c_device_id *id) 689aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe{ 690aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe int rc; 691c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe struct device *dev = &(client->dev); 692c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe 693c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe if (tpm_dev.client != NULL) { 694c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe dev_err(dev, "This driver only supports one client at a time\n"); 695aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return -EBUSY; /* We only support one client */ 696c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe } 697aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 698aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 699c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe dev_err(dev, "no algorithms associated to the i2c bus\n"); 700aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return -ENODEV; 701aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 702aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 703aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe tpm_dev.client = client; 704aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe rc = tpm_tis_i2c_init(&client->dev); 705aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe if (rc != 0) { 706aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe tpm_dev.client = NULL; 707aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe rc = -ENODEV; 708aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe } 709aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return rc; 710aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe} 711aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 71239af33fc458543fd6daaf154e109eba22ab89a8fBill Pembertonstatic int tpm_tis_i2c_remove(struct i2c_client *client) 713aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe{ 714aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe struct tpm_chip *chip = tpm_dev.chip; 715aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe release_locality(chip, chip->vendor.locality, 1); 716aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 717aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* close file handles */ 718aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe tpm_dev_vendor_release(chip); 719aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 720aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* remove hardware */ 721aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe tpm_remove_hardware(chip->dev); 722aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 723aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe /* reset these pointers, otherwise we oops */ 724aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe chip->dev->release = NULL; 725aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe chip->release = NULL; 726aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe tpm_dev.client = NULL; 727aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 728aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe return 0; 729aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe} 730aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 731aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewestatic struct i2c_driver tpm_tis_i2c_driver = { 732aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe .id_table = tpm_tis_i2c_table, 733aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe .probe = tpm_tis_i2c_probe, 734aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe .remove = tpm_tis_i2c_remove, 735aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe .driver = { 736aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe .name = "tpm_i2c_infineon", 737aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe .owner = THIS_MODULE, 738aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe .pm = &tpm_tis_i2c_ops, 739c61c86dd6e0a8037be73cf27212f389e46af60a4Peter Huewe .of_match_table = of_match_ptr(tpm_tis_i2c_of_match), 740aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe }, 741aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe}; 742aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewe 743aad628c1d91a6db57e572e4c1f35e863d81061d7Peter Huewemodule_i2c_driver(tpm_tis_i2c_driver); 744aad628c1d91a6db57e572e4c1f35e863d81061d7Peter HueweMODULE_AUTHOR("Peter Huewe <peter.huewe@infineon.com>"); 745aad628c1d91a6db57e572e4c1f35e863d81061d7Peter HueweMODULE_DESCRIPTION("TPM TIS I2C Infineon Driver"); 746c61c86dd6e0a8037be73cf27212f389e46af60a4Peter HueweMODULE_VERSION("2.2.0"); 747aad628c1d91a6db57e572e4c1f35e863d81061d7Peter HueweMODULE_LICENSE("GPL"); 748