aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/i2c/trivial-devices.txt1
-rw-r--r--drivers/char/tpm/Kconfig9
-rw-r--r--drivers/char/tpm/Makefile1
-rw-r--r--drivers/char/tpm/tpm_i2c_atmel.c284
4 files changed, 295 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index 58454bdfa20e..f1fb26eed0e9 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -15,6 +15,7 @@ adi,adt7461 +/-1C TDM Extended Temp Range I.C
15adt7461 +/-1C TDM Extended Temp Range I.C 15adt7461 +/-1C TDM Extended Temp Range I.C
16at,24c08 i2c serial eeprom (24cxx) 16at,24c08 i2c serial eeprom (24cxx)
17atmel,24c02 i2c serial eeprom (24cxx) 17atmel,24c02 i2c serial eeprom (24cxx)
18atmel,at97sc3204t i2c trusted platform module (TPM)
18catalyst,24c32 i2c serial eeprom 19catalyst,24c32 i2c serial eeprom
19dallas,ds1307 64 x 8, Serial, I2C Real-Time Clock 20dallas,ds1307 64 x 8, Serial, I2C Real-Time Clock
20dallas,ds1338 I2C RTC with 56-Byte NV RAM 21dallas,ds1338 I2C RTC with 56-Byte NV RAM
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index ade71c134a1a..f9085860b716 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -33,6 +33,15 @@ config TCG_TIS
33 from within Linux. To compile this driver as a module, choose 33 from within Linux. To compile this driver as a module, choose
34 M here; the module will be called tpm_tis. 34 M here; the module will be called tpm_tis.
35 35
36config TCG_TIS_I2C_ATMEL
37 tristate "TPM Interface Specification 1.2 Interface (I2C - Atmel)"
38 depends on I2C
39 ---help---
40 If you have an Atmel I2C TPM security chip say Yes and it will be
41 accessible from within Linux.
42 To compile this driver as a module, choose M here; the module will
43 be called tpm_tis_i2c_atmel.
44
36config TCG_TIS_I2C_INFINEON 45config TCG_TIS_I2C_INFINEON
37 tristate "TPM Interface Specification 1.2 Interface (I2C - Infineon)" 46 tristate "TPM Interface Specification 1.2 Interface (I2C - Infineon)"
38 depends on I2C 47 depends on I2C
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 07ee67cf3341..b80a4000daee 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -13,6 +13,7 @@ ifdef CONFIG_TCG_IBMVTPM
13endif 13endif
14endif 14endif
15obj-$(CONFIG_TCG_TIS) += tpm_tis.o 15obj-$(CONFIG_TCG_TIS) += tpm_tis.o
16obj-$(CONFIG_TCG_TIS_I2C_ATMEL) += tpm_i2c_atmel.o
16obj-$(CONFIG_TCG_TIS_I2C_INFINEON) += tpm_i2c_infineon.o 17obj-$(CONFIG_TCG_TIS_I2C_INFINEON) += tpm_i2c_infineon.o
17obj-$(CONFIG_TCG_TIS_I2C_NUVOTON) += tpm_i2c_nuvoton.o 18obj-$(CONFIG_TCG_TIS_I2C_NUVOTON) += tpm_i2c_nuvoton.o
18obj-$(CONFIG_TCG_NSC) += tpm_nsc.o 19obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c
new file mode 100644
index 000000000000..c3cd7fe481a1
--- /dev/null
+++ b/drivers/char/tpm/tpm_i2c_atmel.c
@@ -0,0 +1,284 @@
1/*
2 * ATMEL I2C TPM AT97SC3204T
3 *
4 * Copyright (C) 2012 V Lab Technologies
5 * Teddy Reed <teddy@prosauce.org>
6 * Copyright (C) 2013, Obsidian Research Corp.
7 * Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
8 * Device driver for ATMEL I2C TPMs.
9 *
10 * Teddy Reed determined the basic I2C command flow, unlike other I2C TPM
11 * devices the raw TCG formatted TPM command data is written via I2C and then
12 * raw TCG formatted TPM command data is returned via I2C.
13 *
14 * TGC status/locality/etc functions seen in the LPC implementation do not
15 * seem to be present.
16 *
17 * This program is free software: you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation, either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program. If not, see http://www.gnu.org/licenses/>.
29 */
30#include <linux/init.h>
31#include <linux/module.h>
32#include <linux/moduleparam.h>
33#include <linux/slab.h>
34#include <linux/i2c.h>
35#include "tpm.h"
36
37#define I2C_DRIVER_NAME "tpm_i2c_atmel"
38
39#define TPM_I2C_SHORT_TIMEOUT 750 /* ms */
40#define TPM_I2C_LONG_TIMEOUT 2000 /* 2 sec */
41
42#define ATMEL_STS_OK 1
43
44struct priv_data {
45 size_t len;
46 /* This is the amount we read on the first try. 25 was chosen to fit a
47 * fair number of read responses in the buffer so a 2nd retry can be
48 * avoided in small message cases. */
49 u8 buffer[sizeof(struct tpm_output_header) + 25];
50};
51
52static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len)
53{
54 struct priv_data *priv = chip->vendor.priv;
55 struct i2c_client *client = to_i2c_client(chip->dev);
56 s32 status;
57
58 priv->len = 0;
59
60 if (len <= 2)
61 return -EIO;
62
63 status = i2c_master_send(client, buf, len);
64
65 dev_dbg(chip->dev,
66 "%s(buf=%*ph len=%0zx) -> sts=%d\n", __func__,
67 (int)min_t(size_t, 64, len), buf, len, status);
68 return status;
69}
70
71static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
72{
73 struct priv_data *priv = chip->vendor.priv;
74 struct i2c_client *client = to_i2c_client(chip->dev);
75 struct tpm_output_header *hdr =
76 (struct tpm_output_header *)priv->buffer;
77 u32 expected_len;
78 int rc;
79
80 if (priv->len == 0)
81 return -EIO;
82
83 /* Get the message size from the message header, if we didn't get the
84 * whole message in read_status then we need to re-read the
85 * message. */
86 expected_len = be32_to_cpu(hdr->length);
87 if (expected_len > count)
88 return -ENOMEM;
89
90 if (priv->len >= expected_len) {
91 dev_dbg(chip->dev,
92 "%s early(buf=%*ph count=%0zx) -> ret=%d\n", __func__,
93 (int)min_t(size_t, 64, expected_len), buf, count,
94 expected_len);
95 memcpy(buf, priv->buffer, expected_len);
96 return expected_len;
97 }
98
99 rc = i2c_master_recv(client, buf, expected_len);
100 dev_dbg(chip->dev,
101 "%s reread(buf=%*ph count=%0zx) -> ret=%d\n", __func__,
102 (int)min_t(size_t, 64, expected_len), buf, count,
103 expected_len);
104 return rc;
105}
106
107static void i2c_atmel_cancel(struct tpm_chip *chip)
108{
109 dev_err(chip->dev, "TPM operation cancellation was requested, but is not supported");
110}
111
112static u8 i2c_atmel_read_status(struct tpm_chip *chip)
113{
114 struct priv_data *priv = chip->vendor.priv;
115 struct i2c_client *client = to_i2c_client(chip->dev);
116 int rc;
117
118 /* The TPM fails the I2C read until it is ready, so we do the entire
119 * transfer here and buffer it locally. This way the common code can
120 * properly handle the timeouts. */
121 priv->len = 0;
122 memset(priv->buffer, 0, sizeof(priv->buffer));
123
124
125 /* Once the TPM has completed the command the command remains readable
126 * until another command is issued. */
127 rc = i2c_master_recv(client, priv->buffer, sizeof(priv->buffer));
128 dev_dbg(chip->dev,
129 "%s: sts=%d", __func__, rc);
130 if (rc <= 0)
131 return 0;
132
133 priv->len = rc;
134
135 return ATMEL_STS_OK;
136}
137
138static const struct file_operations i2c_atmel_ops = {
139 .owner = THIS_MODULE,
140 .llseek = no_llseek,
141 .open = tpm_open,
142 .read = tpm_read,
143 .write = tpm_write,
144 .release = tpm_release,
145};