blob: 0ee3a90f5ab966bc7704151eb8f9e27540fcab47 [file] [log] [blame]
Stefan Reinauer3008bbad2011-10-11 14:46:25 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Patrick Georgib890a122015-03-26 15:17:45 +010017 * Foundation, Inc.
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070018 */
19
20/*
21 * The code in this file has been heavily based on the article "Writing a TPM
22 * Device Driver" published on http://ptgmedia.pearsoncmg.com and the
23 * submission by Stefan Berger on Qemu-devel mailing list.
24 *
25 * One principal difference is that in the simplest config the other than 0
26 * TPM localities do not get mapped by some devices (for instance, by
27 * Infineon slb9635), so this driver provides access to locality 0 only.
28 */
29
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070030#include <stdlib.h>
31#include <string.h>
32#include <delay.h>
33#include <arch/io.h>
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070034#include <console/console.h>
Stefan Reinauerd518c7a2013-11-04 17:38:32 -080035#include <tpm.h>
Stefan Reinauerfd4f4132013-06-19 12:25:44 -070036#include <arch/early_variables.h>
Duncan Lauriedd281ed2014-10-30 15:20:19 -070037#include <device/pnp.h>
38#include "chip.h"
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070039
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070040#define PREFIX "lpc_tpm: "
41
42/* coreboot wrapper for TPM driver (start) */
43#define TPM_DEBUG(fmt, args...) \
Stefan Reinauerdfb098d2011-11-17 12:50:54 -080044 if (CONFIG_DEBUG_TPM) { \
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070045 printk(BIOS_DEBUG, PREFIX); \
46 printk(BIOS_DEBUG, fmt , ##args); \
47 }
Aaron Durbinc4220022013-07-24 16:02:14 -050048#define TPM_DEBUG_IO_READ(reg_, val_) \
49 TPM_DEBUG("Read reg 0x%x returns 0x%x\n", (reg_), (val_))
50#define TPM_DEBUG_IO_WRITE(reg_, val_) \
51 TPM_DEBUG("Write reg 0x%x with 0x%x\n", (reg_), (val_))
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070052#define printf(x...) printk(BIOS_ERR, x)
53
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070054/* coreboot wrapper for TPM driver (end) */
55
56#ifndef CONFIG_TPM_TIS_BASE_ADDRESS
57/* Base TPM address standard for x86 systems */
58#define CONFIG_TPM_TIS_BASE_ADDRESS 0xfed40000
59#endif
60
61/* the macro accepts the locality value, but only locality 0 is operational */
62#define TIS_REG(LOCALITY, REG) \
63 (void *)(CONFIG_TPM_TIS_BASE_ADDRESS + (LOCALITY << 12) + REG)
64
65/* hardware registers' offsets */
66#define TIS_REG_ACCESS 0x0
67#define TIS_REG_INT_ENABLE 0x8
68#define TIS_REG_INT_VECTOR 0xc
69#define TIS_REG_INT_STATUS 0x10
70#define TIS_REG_INTF_CAPABILITY 0x14
71#define TIS_REG_STS 0x18
Aaron Durbinc4220022013-07-24 16:02:14 -050072#define TIS_REG_BURST_COUNT 0x19
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070073#define TIS_REG_DATA_FIFO 0x24
74#define TIS_REG_DID_VID 0xf00
75#define TIS_REG_RID 0xf04
76
77/* Some registers' bit field definitions */
78#define TIS_STS_VALID (1 << 7) /* 0x80 */
79#define TIS_STS_COMMAND_READY (1 << 6) /* 0x40 */
80#define TIS_STS_TPM_GO (1 << 5) /* 0x20 */
81#define TIS_STS_DATA_AVAILABLE (1 << 4) /* 0x10 */
82#define TIS_STS_EXPECT (1 << 3) /* 0x08 */
83#define TIS_STS_RESPONSE_RETRY (1 << 1) /* 0x02 */
84
85#define TIS_ACCESS_TPM_REG_VALID_STS (1 << 7) /* 0x80 */
86#define TIS_ACCESS_ACTIVE_LOCALITY (1 << 5) /* 0x20 */
87#define TIS_ACCESS_BEEN_SEIZED (1 << 4) /* 0x10 */
88#define TIS_ACCESS_SEIZE (1 << 3) /* 0x08 */
89#define TIS_ACCESS_PENDING_REQUEST (1 << 2) /* 0x04 */
90#define TIS_ACCESS_REQUEST_USE (1 << 1) /* 0x02 */
91#define TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0) /* 0x01 */
92
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070093/*
94 * Error value returned if a tpm register does not enter the expected state
95 * after continuous polling. No actual TPM register reading ever returns ~0,
96 * so this value is a safe error indication to be mixed with possible status
97 * register values.
98 */
99#define TPM_TIMEOUT_ERR (~0)
100
101/* Error value returned on various TPM driver errors */
102#define TPM_DRIVER_ERR (~0)
103
104 /* 1 second is plenty for anything TPM does.*/
105#define MAX_DELAY_US (1000 * 1000)
106
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700107/*
108 * Structures defined below allow creating descriptions of TPM vendor/device
109 * ID information for run time discovery. The only device the system knows
110 * about at this time is Infineon slb9635
111 */
112struct device_name {
113 u16 dev_id;
114 const char * const dev_name;
115};
116
117struct vendor_name {
118 u16 vendor_id;
119 const char * vendor_name;
Stefan Reinauerc668af72011-10-27 21:28:25 +0000120 const struct device_name* dev_names;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700121};
122
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700123static const struct device_name atmel_devices[] = {
124 {0x3204, "AT97SC3204"},
125 {0xffff}
126};
127
Stefan Reinauerc668af72011-10-27 21:28:25 +0000128static const struct device_name infineon_devices[] = {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700129 {0x000b, "SLB9635 TT 1.2"},
Subrataf4d65872015-05-14 14:38:07 +0530130 {0x001a, "SLB9660 TT 1.2"},
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700131 {0xffff}
132};
133
134static const struct device_name nuvoton_devices[] = {
135 {0x00fe, "NPCT420AA V2"},
136 {0xffff}
137};
138
139static const struct device_name stmicro_devices[] = {
140 {0x0000, "ST33ZP24" },
141 {0xffff}
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700142};
143
144static const struct vendor_name vendor_names[] = {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700145 {0x1114, "Atmel", atmel_devices},
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700146 {0x15d1, "Infineon", infineon_devices},
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700147 {0x1050, "Nuvoton", nuvoton_devices},
148 {0x104a, "ST Microelectronics", stmicro_devices},
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700149};
150
151/*
152 * Cached vendor/device ID pair to indicate that the device has been already
153 * discovered
154 */
Stefan Reinauerc668af72011-10-27 21:28:25 +0000155static u32 vendor_dev_id CAR_GLOBAL;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700156
Aaron Durbinc4220022013-07-24 16:02:14 -0500157static inline u8 tpm_read_status(int locality)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700158{
Julius Werner2f37bd62015-02-19 14:51:15 -0800159 u8 value = read8(TIS_REG(locality, TIS_REG_STS));
Aaron Durbinc4220022013-07-24 16:02:14 -0500160 TPM_DEBUG_IO_READ(TIS_REG_STS, value);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700161 return value;
162}
163
Aaron Durbinc4220022013-07-24 16:02:14 -0500164static inline void tpm_write_status(u8 sts, int locality)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700165{
Aaron Durbinc4220022013-07-24 16:02:14 -0500166 TPM_DEBUG_IO_WRITE(TIS_REG_STS, sts);
Julius Werner2f37bd62015-02-19 14:51:15 -0800167 write8(TIS_REG(locality, TIS_REG_STS), sts);
Aaron Durbinc4220022013-07-24 16:02:14 -0500168}
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700169
Aaron Durbinc4220022013-07-24 16:02:14 -0500170static inline u8 tpm_read_data(int locality)
171{
Julius Werner2f37bd62015-02-19 14:51:15 -0800172 u8 value = read8(TIS_REG(locality, TIS_REG_DATA_FIFO));
Aaron Durbinc4220022013-07-24 16:02:14 -0500173 TPM_DEBUG_IO_READ(TIS_REG_DATA_FIFO, value);
174 return value;
175}
176
177static inline void tpm_write_data(u8 data, int locality)
178{
179 TPM_DEBUG_IO_WRITE(TIS_REG_STS, data);
Julius Werner2f37bd62015-02-19 14:51:15 -0800180 write8(TIS_REG(locality, TIS_REG_DATA_FIFO), data);
Aaron Durbinc4220022013-07-24 16:02:14 -0500181}
182
183static inline u16 tpm_read_burst_count(int locality)
184{
185 u16 count;
Julius Werner2f37bd62015-02-19 14:51:15 -0800186 count = read8(TIS_REG(locality, TIS_REG_BURST_COUNT));
187 count |= read8(TIS_REG(locality, TIS_REG_BURST_COUNT + 1)) << 8;
Aaron Durbinc4220022013-07-24 16:02:14 -0500188 TPM_DEBUG_IO_READ(TIS_REG_BURST_COUNT, count);
189 return count;
190}
191
192static inline u8 tpm_read_access(int locality)
193{
Julius Werner2f37bd62015-02-19 14:51:15 -0800194 u8 value = read8(TIS_REG(locality, TIS_REG_ACCESS));
Aaron Durbinc4220022013-07-24 16:02:14 -0500195 TPM_DEBUG_IO_READ(TIS_REG_ACCESS, value);
196 return value;
197}
198
199static inline void tpm_write_access(u8 data, int locality)
200{
201 TPM_DEBUG_IO_WRITE(TIS_REG_ACCESS, data);
Julius Werner2f37bd62015-02-19 14:51:15 -0800202 write8(TIS_REG(locality, TIS_REG_ACCESS), data);
Aaron Durbinc4220022013-07-24 16:02:14 -0500203}
204
205static inline u32 tpm_read_did_vid(int locality)
206{
Julius Werner2f37bd62015-02-19 14:51:15 -0800207 u32 value = read32(TIS_REG(locality, TIS_REG_DID_VID));
Aaron Durbinc4220022013-07-24 16:02:14 -0500208 TPM_DEBUG_IO_READ(TIS_REG_DID_VID, value);
209 return value;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700210}
211
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700212static inline void tpm_write_int_vector(int vector, int locality)
213{
214 TPM_DEBUG_IO_WRITE(TIS_REG_INT_VECTOR, vector);
Julius Werner2f37bd62015-02-19 14:51:15 -0800215 write8(TIS_REG(locality, TIS_REG_INT_VECTOR), vector & 0xf);
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700216}
217
218static inline void tpm_write_int_polarity(int polarity, int locality)
219{
220 /* Set polarity and leave all other bits at 0 */
221 u32 value = (polarity & 0x3) << 3;
222 TPM_DEBUG_IO_WRITE(TIS_REG_INT_ENABLE, value);
Julius Werner2f37bd62015-02-19 14:51:15 -0800223 write32(TIS_REG(locality, TIS_REG_INT_ENABLE), value);
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700224}
225
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700226/*
Aaron Durbinc4220022013-07-24 16:02:14 -0500227 * tis_wait_sts()
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700228 *
Aaron Durbinc4220022013-07-24 16:02:14 -0500229 * Wait for at least a second for a status to change its state to match the
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700230 * expected state. Normally the transition happens within microseconds.
231 *
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700232 * @locality - locality
233 * @mask - bitmask for the bitfield(s) to watch
234 * @expected - value the field(s) are supposed to be set to
235 *
Aaron Durbinc4220022013-07-24 16:02:14 -0500236 * Returns 0 on success or TPM_TIMEOUT_ERR on timeout.
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700237 */
Aaron Durbinc4220022013-07-24 16:02:14 -0500238static int tis_wait_sts(int locality, u8 mask, u8 expected)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700239{
240 u32 time_us = MAX_DELAY_US;
241 while (time_us > 0) {
Aaron Durbinc4220022013-07-24 16:02:14 -0500242 u8 value = tpm_read_status(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700243 if ((value & mask) == expected)
Aaron Durbinc4220022013-07-24 16:02:14 -0500244 return 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700245 udelay(1); /* 1 us */
246 time_us--;
247 }
248 return TPM_TIMEOUT_ERR;
249}
250
Aaron Durbinc4220022013-07-24 16:02:14 -0500251static inline int tis_wait_ready(int locality)
252{
253 return tis_wait_sts(locality, TIS_STS_COMMAND_READY,
254 TIS_STS_COMMAND_READY);
255}
256
257static inline int tis_wait_valid(int locality)
258{
259 return tis_wait_sts(locality, TIS_STS_VALID, TIS_STS_VALID);
260}
261
262static inline int tis_wait_valid_data(int locality)
263{
264 const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID;
265 return tis_wait_sts(locality, has_data, has_data);
266}
267
268static inline int tis_has_valid_data(int locality)
269{
270 const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID;
271 return (tpm_read_status(locality) & has_data) == has_data;
272}
273
274static inline int tis_expect_data(int locality)
275{
276 return !!(tpm_read_status(locality) & TIS_STS_EXPECT);
277}
278
279/*
280 * tis_wait_access()
281 *
282 * Wait for at least a second for a access to change its state to match the
283 * expected state. Normally the transition happens within microseconds.
284 *
285 * @locality - locality
286 * @mask - bitmask for the bitfield(s) to watch
287 * @expected - value the field(s) are supposed to be set to
288 *
289 * Returns 0 on success or TPM_TIMEOUT_ERR on timeout.
290 */
291static int tis_wait_access(int locality, u8 mask, u8 expected)
292{
293 u32 time_us = MAX_DELAY_US;
294 while (time_us > 0) {
295 u8 value = tpm_read_access(locality);
296 if ((value & mask) == expected)
297 return 0;
298 udelay(1); /* 1 us */
299 time_us--;
300 }
301 return TPM_TIMEOUT_ERR;
302}
303
304static inline int tis_wait_dropped_access(int locality)
305{
306 return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY, 0);
307}
308
309static inline int tis_wait_received_access(int locality)
310{
311 return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY,
312 TIS_ACCESS_ACTIVE_LOCALITY);
313}
314
315static inline int tis_has_access(int locality)
316{
317 return !!(tpm_read_access(locality) & TIS_ACCESS_ACTIVE_LOCALITY);
318}
319
320static inline void tis_request_access(int locality)
321{
322 tpm_write_access(TIS_ACCESS_REQUEST_USE, locality);
323}
324
325static inline void tis_drop_access(int locality)
326{
327 tpm_write_access(TIS_ACCESS_ACTIVE_LOCALITY, locality);
328}
329
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700330/*
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700331 * PC Client Specific TPM Interface Specification section 11.2.12:
332 *
333 * Software must be prepared to send two writes of a "1" to command ready
334 * field: the first to indicate successful read of all the data, thus
335 * clearing the data from the ReadFIFO and freeing the TPM's resources,
336 * and the second to indicate to the TPM it is about to send a new command.
337 *
338 * In practice not all TPMs behave the same so it is necessary to be
339 * flexible when trying to set command ready.
340 *
341 * Returns 0 on success if the TPM is ready for transactions.
342 * Returns TPM_TIMEOUT_ERR if the command ready bit does not get set.
343 */
344static int tis_command_ready(u8 locality)
345{
346 u32 status;
347
348 /* 1st attempt to set command ready */
Aaron Durbinc4220022013-07-24 16:02:14 -0500349 tpm_write_status(TIS_STS_COMMAND_READY, locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700350
351 /* Wait for response */
Aaron Durbinc4220022013-07-24 16:02:14 -0500352 status = tpm_read_status(locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700353
354 /* Check if command ready is set yet */
355 if (status & TIS_STS_COMMAND_READY)
356 return 0;
357
358 /* 2nd attempt to set command ready */
Aaron Durbinc4220022013-07-24 16:02:14 -0500359 tpm_write_status(TIS_STS_COMMAND_READY, locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700360
Aaron Durbinc4220022013-07-24 16:02:14 -0500361 return tis_wait_ready(locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700362}
363
364/*
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700365 * Probe the TPM device and try determining its manufacturer/device name.
366 *
367 * Returns 0 on success (the device is found or was found during an earlier
368 * invocation) or TPM_DRIVER_ERR if the device is not found.
369 */
370static u32 tis_probe(void)
371{
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700372 const char *device_name = "unknown";
373 const char *vendor_name = device_name;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700374 const struct device_name *dev;
375 u32 didvid;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700376 u16 vid, did;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700377 int i;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700378
Aaron Durbincb997d32013-05-10 00:40:56 -0500379 if (car_get_var(vendor_dev_id))
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700380 return 0; /* Already probed. */
381
Aaron Durbinc4220022013-07-24 16:02:14 -0500382 didvid = tpm_read_did_vid(0);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700383 if (!didvid || (didvid == 0xffffffff)) {
384 printf("%s: No TPM device found\n", __FUNCTION__);
385 return TPM_DRIVER_ERR;
386 }
387
Aaron Durbincb997d32013-05-10 00:40:56 -0500388 car_set_var(vendor_dev_id, didvid);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700389
390 vid = didvid & 0xffff;
391 did = (didvid >> 16) & 0xffff;
392 for (i = 0; i < ARRAY_SIZE(vendor_names); i++) {
393 int j = 0;
394 u16 known_did;
395 if (vid == vendor_names[i].vendor_id) {
396 vendor_name = vendor_names[i].vendor_name;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700397 } else {
398 continue;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700399 }
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700400 dev = &vendor_names[i].dev_names[j];
401 while ((known_did = dev->dev_id) != 0xffff) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700402 if (known_did == did) {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700403 device_name = dev->dev_name;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700404 break;
405 }
406 j++;
Subrata41b08d92015-05-14 14:38:07 +0530407 dev = &vendor_names[i].dev_names[j];
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700408 }
409 break;
410 }
411 /* this will have to be converted into debug printout */
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700412 printf("Found TPM %s by %s\n", device_name, vendor_name);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700413 return 0;
414}
415
416/*
417 * tis_senddata()
418 *
419 * send the passed in data to the TPM device.
420 *
421 * @data - address of the data to send, byte by byte
422 * @len - length of the data to send
423 *
424 * Returns 0 on success, TPM_DRIVER_ERR on error (in case the device does
425 * not accept the entire command).
426 */
427static u32 tis_senddata(const u8 * const data, u32 len)
428{
429 u32 offset = 0;
430 u16 burst = 0;
431 u32 max_cycles = 0;
432 u8 locality = 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700433
Aaron Durbinc4220022013-07-24 16:02:14 -0500434 if (tis_wait_ready(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700435 printf("%s:%d - failed to get 'command_ready' status\n",
436 __FILE__, __LINE__);
437 return TPM_DRIVER_ERR;
438 }
Aaron Durbinc4220022013-07-24 16:02:14 -0500439 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700440
441 while (1) {
442 unsigned count;
443
444 /* Wait till the device is ready to accept more data. */
445 while (!burst) {
446 if (max_cycles++ == MAX_DELAY_US) {
447 printf("%s:%d failed to feed %d bytes of %d\n",
448 __FILE__, __LINE__, len - offset, len);
449 return TPM_DRIVER_ERR;
450 }
451 udelay(1);
Aaron Durbinc4220022013-07-24 16:02:14 -0500452 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700453 }
454
455 max_cycles = 0;
456
457 /*
458 * Calculate number of bytes the TPM is ready to accept in one
459 * shot.
460 *
461 * We want to send the last byte outside of the loop (hence
462 * the -1 below) to make sure that the 'expected' status bit
463 * changes to zero exactly after the last byte is fed into the
464 * FIFO.
465 */
466 count = min(burst, len - offset - 1);
467 while (count--)
Aaron Durbinc4220022013-07-24 16:02:14 -0500468 tpm_write_data(data[offset++], locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700469
Aaron Durbinc4220022013-07-24 16:02:14 -0500470 if (tis_wait_valid(locality) || !tis_expect_data(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700471 printf("%s:%d TPM command feed overflow\n",
472 __FILE__, __LINE__);
473 return TPM_DRIVER_ERR;
474 }
475
Aaron Durbinc4220022013-07-24 16:02:14 -0500476 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700477 if ((offset == (len - 1)) && burst)
478 /*
479 * We need to be able to send the last byte to the
480 * device, so burst size must be nonzero before we
481 * break out.
482 */
483 break;
484 }
485
486 /* Send the last byte. */
Aaron Durbinc4220022013-07-24 16:02:14 -0500487 tpm_write_data(data[offset++], locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700488
489 /*
490 * Verify that TPM does not expect any more data as part of this
491 * command.
492 */
Aaron Durbinc4220022013-07-24 16:02:14 -0500493 if (tis_wait_valid(locality) || tis_expect_data(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700494 printf("%s:%d unexpected TPM status 0x%x\n",
Aaron Durbinc4220022013-07-24 16:02:14 -0500495 __FILE__, __LINE__, tpm_read_status(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700496 return TPM_DRIVER_ERR;
497 }
498
499 /* OK, sitting pretty, let's start the command execution. */
Aaron Durbinc4220022013-07-24 16:02:14 -0500500 tpm_write_status(TIS_STS_TPM_GO, locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700501
502 return 0;
503}
504
505/*
506 * tis_readresponse()
507 *
508 * read the TPM device response after a command was issued.
509 *
510 * @buffer - address where to read the response, byte by byte.
511 * @len - pointer to the size of buffer
512 *
513 * On success stores the number of received bytes to len and returns 0. On
514 * errors (misformatted TPM data or synchronization problems) returns
515 * TPM_DRIVER_ERR.
516 */
517static u32 tis_readresponse(u8 *buffer, size_t *len)
518{
519 u16 burst_count;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700520 u32 offset = 0;
521 u8 locality = 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700522 u32 expected_count = *len;
523 int max_cycles = 0;
524
525 /* Wait for the TPM to process the command */
Aaron Durbinc4220022013-07-24 16:02:14 -0500526 if (tis_wait_valid_data(locality)) {
527 printf("%s:%d failed processing command\n", __FILE__, __LINE__);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700528 return TPM_DRIVER_ERR;
529 }
530
531 do {
Aaron Durbinc4220022013-07-24 16:02:14 -0500532 while ((burst_count = tpm_read_burst_count(locality)) == 0) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700533 if (max_cycles++ == MAX_DELAY_US) {
534 printf("%s:%d TPM stuck on read\n",
535 __FILE__, __LINE__);
536 return TPM_DRIVER_ERR;
537 }
538 udelay(1);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700539 }
540
541 max_cycles = 0;
542
543 while (burst_count-- && (offset < expected_count)) {
Aaron Durbinc4220022013-07-24 16:02:14 -0500544 buffer[offset++] = tpm_read_data(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700545 if (offset == 6) {
546 /*
547 * We got the first six bytes of the reply,
548 * let's figure out how many bytes to expect
549 * total - it is stored as a 4 byte number in
550 * network order, starting with offset 2 into
551 * the body of the reply.
552 */
553 u32 real_length;
554 memcpy(&real_length,
555 buffer + 2,
556 sizeof(real_length));
557 expected_count = be32_to_cpu(real_length);
558
559 if ((expected_count < offset) ||
560 (expected_count > *len)) {
561 printf("%s:%d bad response size %d\n",
562 __FILE__, __LINE__,
563 expected_count);
564 return TPM_DRIVER_ERR;
565 }
566 }
567 }
568
569 /* Wait for the next portion */
Aaron Durbinc4220022013-07-24 16:02:14 -0500570 if (tis_wait_valid(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700571 printf("%s:%d failed to read response\n",
572 __FILE__, __LINE__);
573 return TPM_DRIVER_ERR;
574 }
575
576 if (offset == expected_count)
577 break; /* We got all we need */
578
Aaron Durbinc4220022013-07-24 16:02:14 -0500579 } while (tis_has_valid_data(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700580
Aaron Durbinc4220022013-07-24 16:02:14 -0500581 /* * Make sure we indeed read all there was. */
582 if (tis_has_valid_data(locality)) {
583 printf("%s:%d wrong receive status: %x %d bytes left\n",
584 __FILE__, __LINE__, tpm_read_status(locality),
585 tpm_read_burst_count(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700586 return TPM_DRIVER_ERR;
587 }
588
589 /* Tell the TPM that we are done. */
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700590 if (tis_command_ready(locality) == TPM_TIMEOUT_ERR)
591 return TPM_DRIVER_ERR;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700592
593 *len = offset;
594 return 0;
595}
596
597/*
598 * tis_init()
599 *
600 * Initialize the TPM device. Returns 0 on success or TPM_DRIVER_ERR on
601 * failure (in case device probing did not succeed).
602 */
603int tis_init(void)
604{
605 if (tis_probe())
606 return TPM_DRIVER_ERR;
607 return 0;
608}
609
610/*
611 * tis_open()
612 *
613 * Requests access to locality 0 for the caller. After all commands have been
614 * completed the caller is supposed to call tis_close().
615 *
616 * Returns 0 on success, TPM_DRIVER_ERR on failure.
617 */
618int tis_open(void)
619{
620 u8 locality = 0; /* we use locality zero for everything */
621
622 if (tis_close())
623 return TPM_DRIVER_ERR;
624
625 /* now request access to locality */
Aaron Durbinc4220022013-07-24 16:02:14 -0500626 tis_request_access(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700627
628 /* did we get a lock? */
Aaron Durbinc4220022013-07-24 16:02:14 -0500629 if (tis_wait_received_access(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700630 printf("%s:%d - failed to lock locality %d\n",
631 __FILE__, __LINE__, locality);
632 return TPM_DRIVER_ERR;
633 }
634
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700635 /* Certain TPMs seem to need some delay here or they hang... */
636 udelay(10);
637
638 if (tis_command_ready(locality) == TPM_TIMEOUT_ERR)
639 return TPM_DRIVER_ERR;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700640
641 return 0;
642}
643
644/*
645 * tis_close()
646 *
Martin Roth56889792013-07-09 21:39:46 -0600647 * terminate the current session with the TPM by releasing the locked
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700648 * locality. Returns 0 on success of TPM_DRIVER_ERR on failure (in case lock
649 * removal did not succeed).
650 */
651int tis_close(void)
652{
653 u8 locality = 0;
Aaron Durbinc4220022013-07-24 16:02:14 -0500654 if (tis_has_access(locality)) {
655 tis_drop_access(locality);
656 if (tis_wait_dropped_access(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700657 printf("%s:%d - failed to release locality %d\n",
658 __FILE__, __LINE__, locality);
659 return TPM_DRIVER_ERR;
660 }
661 }
662 return 0;
663}
664
665/*
666 * tis_sendrecv()
667 *
668 * Send the requested data to the TPM and then try to get its response
669 *
670 * @sendbuf - buffer of the data to send
671 * @send_size size of the data to send
672 * @recvbuf - memory to save the response to
673 * @recv_len - pointer to the size of the response buffer
674 *
675 * Returns 0 on success (and places the number of response bytes at recv_len)
676 * or TPM_DRIVER_ERR on failure.
677 */
678int tis_sendrecv(const uint8_t *sendbuf, size_t send_size,
679 uint8_t *recvbuf, size_t *recv_len)
680{
681 if (tis_senddata(sendbuf, send_size)) {
682 printf("%s:%d failed sending data to TPM\n",
683 __FILE__, __LINE__);
684 return TPM_DRIVER_ERR;
685 }
686
687 return tis_readresponse(recvbuf, recv_len);
688}
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700689
690#ifdef __RAMSTAGE__
691
692/*
693 * tis_setup_interrupt()
694 *
695 * Set up the interrupt vector and polarity for locality 0 and
696 * disable all interrupts so they are unused in firmware but can
697 * be enabled by the OS.
698 *
699 * The values used here must match what is passed in the TPM ACPI
700 * device if ACPI is used on the platform.
701 *
702 * @vector - TPM interrupt vector
703 * @polarity - TPM interrupt polarity
704 *
705 * Returns 0 on success, TPM_DRIVER_ERR on failure.
706 */
707static int tis_setup_interrupt(int vector, int polarity)
708{
709 u8 locality = 0;
710 int has_access = tis_has_access(locality);
711
712 /* Open connection and request access if not already granted */
713 if (!has_access && tis_open() < 0)
714 return TPM_DRIVER_ERR;
715
716 /* Set TPM interrupt vector */
717 tpm_write_int_vector(vector, locality);
718
719 /* Set TPM interupt polarity and disable interrupts */
720 tpm_write_int_polarity(polarity, locality);
721
722 /* Close connection if it was opened */
723 if (!has_access && tis_close() < 0)
724 return TPM_DRIVER_ERR;
725
726 return 0;
727}
728
729static void lpc_tpm_read_resources(struct device *dev)
730{
731 /* Static 5K memory region specified in Kconfig */
732 mmio_resource(dev, 0, CONFIG_TPM_TIS_BASE_ADDRESS >> 10, 0x5000 >> 10);
733}
734
735static void lpc_tpm_set_resources(struct device *dev)
736{
737 tpm_config_t *config = (tpm_config_t *)dev->chip_info;
738 struct resource *res;
739
740 for (res = dev->resource_list; res; res = res->next) {
741 if (!(res->flags & IORESOURCE_ASSIGNED))
742 continue;
743
744 if (res->flags & IORESOURCE_IRQ) {
745 /* Set interrupt vector */
746 tis_setup_interrupt((int)res->base,
747 config->irq_polarity);
748 } else {
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700749 continue;
750 }
751
752 res->flags |= IORESOURCE_STORED;
753 report_resource_stored(dev, res, " <tpm>");
754 }
755}
756
757static struct device_operations lpc_tpm_ops = {
758 .read_resources = &lpc_tpm_read_resources,
759 .set_resources = &lpc_tpm_set_resources,
760};
761
762static struct pnp_info pnp_dev_info[] = {
763 { .flags = PNP_IRQ0 }
764};
765
766static void enable_dev(struct device *dev)
767{
768 pnp_enable_devices(dev, &lpc_tpm_ops,
769 ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
770}
771
772struct chip_operations drivers_pc80_tpm_ops = {
773 CHIP_NAME("LPC TPM")
774 .enable_dev = enable_dev
775};
776
777#endif /* __RAMSTAGE__ */