Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: drivers/tpm/slb9635_i2c/tpm_tis_i2c.c

Issue 6683023: Add Infineon v05 TPM driver (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/u-boot-next.git@chromeos-v2010.09
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2011 Infineon Technologies
3 *
4 * Authors:
5 *
6 * Device driver for TCG/TCPA TPM (trusted platform module).
7 * Specifications at www.trustedcomputinggroup.org
8 *
9 * This device driver implements the TPM interface as defined in
10 * the TCG TPM Interface Spec version 1.2, revision 1.0 and the
11 * Infineon I2C Protocol Stack Specification v0.12.
12 *
13 * It is based on the original tpm_tis device driver from Leendert van
14 * Dorn and Kyleen Hall.
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License as
18 * published by the Free Software Foundation, version 2 of the
19 * License.
20 *
21 */
22 #include <common.h>
23 #include <i2c.h>
24 #include <linux/types.h>
25
26 #include "compatibility.h"
27 #include "tpm.h"
28
29 /* Address of the TPM on the I2C bus */
30 #define TPM_I2C_ADDR 0x20
31 /* Max. number of retries for iic read/write */
32 #define MAX_COUNT 3
33 /* Sleep between i2c transfers in ms */
34 #define TPM_MSLEEP_TIME 1
35 /* max. buffer size required by TPM commands/results */
36 #define TPM_BUFSIZE 4096
37
38 /* Structure to store I2C TPM specific stuff */
39 struct tpm_inf_dev {
40 uint addr;
41 u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */
42 };
43
44 static struct tpm_inf_dev tpm_dev = {
45 .addr = TPM_I2C_ADDR
46 };
47
48 /* I2C Read/Write Functions from U-Boot */
49 extern int i2c_read_data(uchar chip, uchar *buffer, int len);
50 extern int i2c_write_data(uchar chip, uchar *buffer, int len);
51
52 int iic_tpm_read(uint addr, uchar *buffer, int len)
53 {
54 int rc;
55 int count = 0;
56
57 do {
58 rc = i2c_write_data(tpm_dev.addr, (uchar *) &addr, 1);
59 msleep2(TPM_MSLEEP_TIME);
60 //udelay(TPM_MSLEEP_TIME * 1000);
61 } while ((rc) && (count++ < MAX_COUNT));
62
63 if (rc)
64 return -rc;
65
66 count = 0;
67 do {
68 rc = i2c_read_data(tpm_dev.addr, buffer, len);
69 msleep2(TPM_MSLEEP_TIME);
70 //udelay(TPM_MSLEEP_TIME * 1000);
71 } while ((rc) && (count++ < MAX_COUNT));
72
73 if (rc)
74 return -rc;
75
76 return 0;
77 }
78
79 int iic_tpm_write(uint addr, const uchar *buffer, int len)
80 {
81 int rc;
82 int count = 0;
83
84 /* prepare send buffer */
85 tpm_dev.buf[0] = addr;
86 memcpy(&(tpm_dev.buf[1]), buffer, len);
87
88 do {
89 rc = i2c_write_data(tpm_dev.addr, tpm_dev.buf, len + 1);
90 } while ((rc) && (count++ < MAX_COUNT));
91
92 if (rc)
93 return -rc;
94
95 return 0;
96 }
97
98 #define TPM_HEADER_SIZE 10
99
100 enum tis_access {
101 TPM_ACCESS_VALID = 0x80,
102 TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
103 TPM_ACCESS_REQUEST_PENDING = 0x04,
104 TPM_ACCESS_REQUEST_USE = 0x02,
105 };
106
107 enum tis_status {
108 TPM_STS_VALID = 0x80,
109 TPM_STS_COMMAND_READY = 0x40,
110 TPM_STS_GO = 0x20,
111 TPM_STS_DATA_AVAIL = 0x10,
112 TPM_STS_DATA_EXPECT = 0x08,
113 };
114
115 enum tis_defaults {
116 TIS_SHORT_TIMEOUT = 750, /* ms */
117 TIS_LONG_TIMEOUT = 2000, /* 2 sec */
118 };
119
120 #define TPM_ACCESS(l) (0x0000 | ((l) << 4))
121 #define TPM_STS(l) (0x0001 | ((l) << 4))
122 #define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4))
123 #define TPM_DID_VID(l) (0x0006 | ((l) << 4))
124
125 static int check_locality(struct tpm_chip *chip, int l)
126 {
127 u8 buf;
128
129 if (iic_tpm_read(TPM_ACCESS(l), &buf, 1) < 0)
130 return -1;
131
132 if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
133 (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
134 return chip->vendor.locality = l;
135
136 return -1;
137 }
138
139 static void release_locality(struct tpm_chip *chip, int l, int force)
140 {
141 u8 buf;
142 if (iic_tpm_read(TPM_ACCESS(l), &buf, 1) < 0)
143 return;
144
145 if (force || (buf & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
146 (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) {
147 buf = TPM_ACCESS_ACTIVE_LOCALITY,
148 iic_tpm_write(TPM_ACCESS(l), &buf, 1);
149 }
150 }
151
152 static int request_locality(struct tpm_chip *chip, int l)
153 {
154 unsigned long stop;
155 u8 buf = TPM_ACCESS_REQUEST_USE;
156
157 if (check_locality(chip, l) >= 0)
158 return l;
159
160 iic_tpm_write(TPM_ACCESS(l), &buf, 1);
161
162 /* wait for burstcount */
163 jiffies = 0;
164 stop = jiffies + chip->vendor.timeout_a;
165 do {
166 if (check_locality(chip, l) >= 0)
167 return l;
168 msleep2(TPM_TIMEOUT);
169 } while (time_before(jiffies, stop));
170 return -1;
171 }
172
173 static u8 tpm_tis_i2c_status(struct tpm_chip *chip)
174 {
175 /* NOTE: since i2c read may fail, return 0 in this case --> time-out */
176 u8 buf;
177 if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0)
178 return 0;
179 else
180 return buf;
181 }
182
183 static void tpm_tis_i2c_ready(struct tpm_chip *chip)
184 {
185 /* this causes the current command to be aborted */
186 u8 buf = TPM_STS_COMMAND_READY;
187 iic_tpm_write(TPM_STS(chip->vendor.locality), &buf, 1);
188 }
189
190 static int get_burstcount(struct tpm_chip *chip)
191 {
192 unsigned long stop;
193 int burstcnt;
194 u8 buf[3];
195
196 /* wait for burstcount */
197 /* which timeout value, spec has 2 answers (c & d) */
198 jiffies = 0;
199 stop = jiffies + chip->vendor.timeout_d;
200 do {
201 /* Note: STS is little endian */
202 if (iic_tpm_read(TPM_STS(chip->vendor.locality) + 1, buf, 3) <
203 0) {
204 burstcnt = 0;
205 } else {
206 burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0];
207 }
208
209 if (burstcnt)
210 return burstcnt;
211 msleep2(TPM_TIMEOUT);
212 } while (time_before(jiffies, stop));
213 return -EBUSY;
214 }
215
216 static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout)
217 {
218 unsigned long stop;
219 u8 status;
220
221 /* check current status */
222 status = tpm_tis_i2c_status(chip);
223 if ((status & mask) == mask)
224 return 0;
225
226 jiffies = 0;
227 stop = jiffies + timeout;
228 do {
229 msleep2(TPM_TIMEOUT);
230 status = tpm_tis_i2c_status(chip);
231 if ((status & mask) == mask)
232 return 0;
233 } while (time_before(jiffies, stop));
234
235 return -ETIME;
236 }
237
238 static int recv_data(struct tpm_chip *chip, u8 * buf, size_t count)
239 {
240 size_t size = 0, burstcnt;
241 int rc;
242
243 while (size < count &&
244 wait_for_stat(chip,
245 TPM_STS_DATA_AVAIL | TPM_STS_VALID,
246 chip->vendor.timeout_c)
247 == 0) {
248 burstcnt = get_burstcount(chip);
249
250 /* wait for positive burst count */
251 if (burstcnt > 0) {
252 /* limit received data to max. left */
253 if ((size_t) burstcnt > (count - size))
254 burstcnt = count - size;
255
256 rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality),
257 &(buf[size]), burstcnt);
258 if (rc == 0)
259 size += burstcnt;
260 }
261 }
262
263 return size;
264 }
265
266 static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 * buf, size_t count)
267 {
268 int size = 0;
269 int expected, status;
270
271 if (count < TPM_HEADER_SIZE) {
272 size = -EIO;
273 goto out;
274 }
275
276 /* read first 10 bytes, including tag, paramsize, and result */
277 size = recv_data(chip, buf, TPM_HEADER_SIZE);
278 if (size < TPM_HEADER_SIZE) {
279 dev_err(chip->dev, "Unable to read header\n");
280 goto out;
281 }
282
283 expected = switch_endian32(&buf[TPM_RSP_SIZE_BYTE]);
284 if ((size_t) expected > count) {
285 size = -EIO;
286 goto out;
287 }
288
289 size += recv_data(chip, &buf[TPM_HEADER_SIZE],
290 expected - TPM_HEADER_SIZE);
291 if (size < expected) {
292 dev_err(chip->dev, "Unable to read remainder of result\n");
293 size = -ETIME;
294 goto out;
295 }
296
297 wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c);
298 status = tpm_tis_i2c_status(chip);
299 if (status & TPM_STS_DATA_AVAIL) { /* retry? */
300 dev_err(chip->dev, "Error left over data\n");
301 size = -EIO;
302 goto out;
303 }
304
305 out:
306 tpm_tis_i2c_ready(chip);
307 release_locality(chip, chip->vendor.locality, 0);
308
309 return size;
310 }
311
312 static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 * buf, size_t len)
313 {
314 int rc, status, burstcnt;
315 size_t count = 0;
316 u8 sts = TPM_STS_GO;
317
318 if (request_locality(chip, 0) < 0)
319 return -EBUSY;
320
321 status = tpm_tis_i2c_status(chip);
322 if ((status & TPM_STS_COMMAND_READY) == 0) {
323 tpm_tis_i2c_ready(chip);
324 if (wait_for_stat
325 (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b) < 0) {
326 rc = -ETIME;
327 goto out_err;
328 }
329 }
330
331 while (count < len - 1) {
332 burstcnt = get_burstcount(chip);
333 /* wait for positive burst count */
334 if (burstcnt > 0) {
335 if ((size_t) burstcnt > (len - 1 - count))
336 burstcnt = len - 1 - count;
337
338 #ifdef CONFIG_TPM_I2C_BURST_LIMITATION
339 if (burstcnt > CONFIG_TPM_I2C_BURST_LIMITATION)
340 burstcnt = CONFIG_TPM_I2C_BURST_LIMITATION;
341 #endif
342 rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality),
343 &(buf[count]), burstcnt);
344 if (rc == 0)
345 count += burstcnt;
346
347 wait_for_stat(chip, TPM_STS_VALID,
348 chip->vendor.timeout_c);
349
350 status = tpm_tis_i2c_status(chip);
351 if ((status & TPM_STS_DATA_EXPECT) == 0) {
352 rc = -EIO;
353 goto out_err;
354 }
355 }
356 }
357
358 /* write last byte */
359 iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1);
360 wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c);
361 status = tpm_tis_i2c_status(chip);
362 if ((status & TPM_STS_DATA_EXPECT) != 0) {
363 rc = -EIO;
364 goto out_err;
365 }
366
367 /* go and do it */
368 iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1);
369
370 return len;
371 out_err:
372 tpm_tis_i2c_ready(chip);
373 release_locality(chip, chip->vendor.locality, 0);
374
375 return rc;
376 }
377
378 static struct tpm_vendor_specific tpm_tis_i2c = {
379 .status = tpm_tis_i2c_status,
380 .recv = tpm_tis_i2c_recv,
381 .send = tpm_tis_i2c_send,
382 .cancel = tpm_tis_i2c_ready,
383 .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
384 .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
385 .req_canceled = TPM_STS_COMMAND_READY,
386 };
387
388 /* initialisation of i2c tpm */
389 int tpm_tis_i2c_init(struct device *dev)
390 {
391 u32 vendor;
392 int rc = 0;
393 u8 buf[4];
394 struct tpm_chip *chip;
395
396 chip = tpm_register_hardware(dev, &tpm_tis_i2c);
397 if (chip < 0) {
398 rc = -ENODEV;
399 goto out_err;
400 }
401
402 /* Disable interrupts */
403 chip->vendor.irq = 0;
404
405 /* Default timeouts */
406 chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
407 chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
408 chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
409 chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
410
411 if (request_locality(chip, 0) != 0) {
412 rc = -ENODEV;
413 goto out_err;
414 }
415
416 /* read four bytes from DID_VID register */
417 if (iic_tpm_read(TPM_DID_VID(0), &(buf[0]), 4) < 0) {
418 rc = -EIO;
419 goto out_err;
420 }
421
422 /* create DID_VID register value, after swapping to little-endian */
423 vendor = switch_endian32(&buf[0]);
424
425 dev_info(dev, "1.2 TPM (device-id 0x%X)\n", vendor >> 16);
426
427 return 0;
428
429 out_err:
430 return rc;
431 }
432
433 void tpm_tis_i2c_cleanup(struct tpm_chip *chip)
434 {
435 release_locality(chip, chip->vendor.locality, 1);
436 }
437
438 module_init(init_tis_i2c);
439 module_exit(cleanup_tis_i2c);
440 MODULE_DESCRIPTION("TPM Driver");
441 MODULE_VERSION("2.0.99");
442 MODULE_LICENSE("GPL");
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698