blob: 8c01ac3d3d8b25167c6bdef4a467842716e7857c [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.
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070014 */
15
16/*
17 * The code in this file has been heavily based on the article "Writing a TPM
18 * Device Driver" published on http://ptgmedia.pearsoncmg.com and the
19 * submission by Stefan Berger on Qemu-devel mailing list.
20 *
21 * One principal difference is that in the simplest config the other than 0
22 * TPM localities do not get mapped by some devices (for instance, by
23 * Infineon slb9635), so this driver provides access to locality 0 only.
24 */
25
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070026#include <stdlib.h>
27#include <string.h>
28#include <delay.h>
29#include <arch/io.h>
Naresh G Solanki80ff0382016-11-15 11:01:33 +053030#include <arch/acpi.h>
31#include <arch/acpigen.h>
32#include <arch/acpi_device.h>
33#include <device/device.h>
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070034#include <console/console.h>
Philipp Deppenwiesed88fb362017-10-18 20:26:18 +020035#include <security/tpm/tis.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: "
Naresh G Solanki80ff0382016-11-15 11:01:33 +053041/* TCG Physical Presence Interface */
42#define TPM_PPI_UUID "3dddfaa6-361b-4eb4-a424-8d10089d1653"
43/* TCG Memory Clear Interface */
44#define TPM_MCI_UUID "376054ed-cc13-4675-901c-4756d7f2d45d"
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070045/* coreboot wrapper for TPM driver (start) */
46#define TPM_DEBUG(fmt, args...) \
Denis 'GNUtoo' Carikli0e92bb02016-02-20 17:32:03 +010047 if (IS_ENABLED(CONFIG_DEBUG_TPM)) { \
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070048 printk(BIOS_DEBUG, PREFIX); \
49 printk(BIOS_DEBUG, fmt , ##args); \
50 }
Aaron Durbinc4220022013-07-24 16:02:14 -050051#define TPM_DEBUG_IO_READ(reg_, val_) \
52 TPM_DEBUG("Read reg 0x%x returns 0x%x\n", (reg_), (val_))
53#define TPM_DEBUG_IO_WRITE(reg_, val_) \
54 TPM_DEBUG("Write reg 0x%x with 0x%x\n", (reg_), (val_))
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070055#define printf(x...) printk(BIOS_ERR, x)
56
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070057/* coreboot wrapper for TPM driver (end) */
58
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070059/* the macro accepts the locality value, but only locality 0 is operational */
60#define TIS_REG(LOCALITY, REG) \
Martin Rothb9810a42017-07-23 20:00:04 -060061 (void *)(CONFIG_TPM_TIS_BASE_ADDRESS + (LOCALITY << 12) + REG)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070062
63/* hardware registers' offsets */
64#define TIS_REG_ACCESS 0x0
65#define TIS_REG_INT_ENABLE 0x8
66#define TIS_REG_INT_VECTOR 0xc
67#define TIS_REG_INT_STATUS 0x10
68#define TIS_REG_INTF_CAPABILITY 0x14
69#define TIS_REG_STS 0x18
Aaron Durbinc4220022013-07-24 16:02:14 -050070#define TIS_REG_BURST_COUNT 0x19
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070071#define TIS_REG_DATA_FIFO 0x24
72#define TIS_REG_DID_VID 0xf00
73#define TIS_REG_RID 0xf04
74
75/* Some registers' bit field definitions */
76#define TIS_STS_VALID (1 << 7) /* 0x80 */
77#define TIS_STS_COMMAND_READY (1 << 6) /* 0x40 */
78#define TIS_STS_TPM_GO (1 << 5) /* 0x20 */
79#define TIS_STS_DATA_AVAILABLE (1 << 4) /* 0x10 */
80#define TIS_STS_EXPECT (1 << 3) /* 0x08 */
81#define TIS_STS_RESPONSE_RETRY (1 << 1) /* 0x02 */
82
83#define TIS_ACCESS_TPM_REG_VALID_STS (1 << 7) /* 0x80 */
84#define TIS_ACCESS_ACTIVE_LOCALITY (1 << 5) /* 0x20 */
85#define TIS_ACCESS_BEEN_SEIZED (1 << 4) /* 0x10 */
86#define TIS_ACCESS_SEIZE (1 << 3) /* 0x08 */
87#define TIS_ACCESS_PENDING_REQUEST (1 << 2) /* 0x04 */
88#define TIS_ACCESS_REQUEST_USE (1 << 1) /* 0x02 */
89#define TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0) /* 0x01 */
90
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070091/*
92 * Error value returned if a tpm register does not enter the expected state
93 * after continuous polling. No actual TPM register reading ever returns ~0,
94 * so this value is a safe error indication to be mixed with possible status
95 * register values.
96 */
97#define TPM_TIMEOUT_ERR (~0)
98
99/* Error value returned on various TPM driver errors */
100#define TPM_DRIVER_ERR (~0)
101
102 /* 1 second is plenty for anything TPM does.*/
103#define MAX_DELAY_US (1000 * 1000)
104
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700105/*
106 * Structures defined below allow creating descriptions of TPM vendor/device
107 * ID information for run time discovery. The only device the system knows
108 * about at this time is Infineon slb9635
109 */
110struct device_name {
111 u16 dev_id;
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +0200112 const char *const dev_name;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700113};
114
115struct vendor_name {
116 u16 vendor_id;
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +0200117 const char *vendor_name;
118 const struct device_name *dev_names;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700119};
120
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700121static const struct device_name atmel_devices[] = {
122 {0x3204, "AT97SC3204"},
123 {0xffff}
124};
125
Stefan Reinauerc668af72011-10-27 21:28:25 +0000126static const struct device_name infineon_devices[] = {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700127 {0x000b, "SLB9635 TT 1.2"},
Subrata Banik5b8c4a72016-11-11 09:28:45 +0530128#if IS_ENABLED(CONFIG_TPM2)
Kamil Wcislobf5ccfd2017-10-12 13:12:11 +0200129 {0x001a, "SLB9665 TT 2.0"},
Subrata Banik5b8c4a72016-11-11 09:28:45 +0530130 {0x001b, "SLB9670 TT 2.0"},
131#else
Kamil Wcislobf5ccfd2017-10-12 13:12:11 +0200132 {0x001a, "SLB9660 TT 1.2"},
Wenkai Du641529b2015-05-29 10:54:27 -0700133 {0x001b, "SLB9670 TT 1.2"},
Subrata Banik5b8c4a72016-11-11 09:28:45 +0530134#endif
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700135 {0xffff}
136};
137
138static const struct device_name nuvoton_devices[] = {
139 {0x00fe, "NPCT420AA V2"},
140 {0xffff}
141};
142
143static const struct device_name stmicro_devices[] = {
144 {0x0000, "ST33ZP24" },
145 {0xffff}
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700146};
147
148static const struct vendor_name vendor_names[] = {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700149 {0x1114, "Atmel", atmel_devices},
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700150 {0x15d1, "Infineon", infineon_devices},
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700151 {0x1050, "Nuvoton", nuvoton_devices},
152 {0x104a, "ST Microelectronics", stmicro_devices},
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700153};
154
155/*
156 * Cached vendor/device ID pair to indicate that the device has been already
157 * discovered
158 */
Stefan Reinauerc668af72011-10-27 21:28:25 +0000159static u32 vendor_dev_id CAR_GLOBAL;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700160
Aaron Durbinc4220022013-07-24 16:02:14 -0500161static inline u8 tpm_read_status(int locality)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700162{
Julius Werner2f37bd62015-02-19 14:51:15 -0800163 u8 value = read8(TIS_REG(locality, TIS_REG_STS));
Aaron Durbinc4220022013-07-24 16:02:14 -0500164 TPM_DEBUG_IO_READ(TIS_REG_STS, value);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700165 return value;
166}
167
Aaron Durbinc4220022013-07-24 16:02:14 -0500168static inline void tpm_write_status(u8 sts, int locality)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700169{
Aaron Durbinc4220022013-07-24 16:02:14 -0500170 TPM_DEBUG_IO_WRITE(TIS_REG_STS, sts);
Julius Werner2f37bd62015-02-19 14:51:15 -0800171 write8(TIS_REG(locality, TIS_REG_STS), sts);
Aaron Durbinc4220022013-07-24 16:02:14 -0500172}
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700173
Aaron Durbinc4220022013-07-24 16:02:14 -0500174static inline u8 tpm_read_data(int locality)
175{
Julius Werner2f37bd62015-02-19 14:51:15 -0800176 u8 value = read8(TIS_REG(locality, TIS_REG_DATA_FIFO));
Aaron Durbinc4220022013-07-24 16:02:14 -0500177 TPM_DEBUG_IO_READ(TIS_REG_DATA_FIFO, value);
178 return value;
179}
180
181static inline void tpm_write_data(u8 data, int locality)
182{
183 TPM_DEBUG_IO_WRITE(TIS_REG_STS, data);
Julius Werner2f37bd62015-02-19 14:51:15 -0800184 write8(TIS_REG(locality, TIS_REG_DATA_FIFO), data);
Aaron Durbinc4220022013-07-24 16:02:14 -0500185}
186
187static inline u16 tpm_read_burst_count(int locality)
188{
189 u16 count;
Julius Werner2f37bd62015-02-19 14:51:15 -0800190 count = read8(TIS_REG(locality, TIS_REG_BURST_COUNT));
191 count |= read8(TIS_REG(locality, TIS_REG_BURST_COUNT + 1)) << 8;
Aaron Durbinc4220022013-07-24 16:02:14 -0500192 TPM_DEBUG_IO_READ(TIS_REG_BURST_COUNT, count);
193 return count;
194}
195
196static inline u8 tpm_read_access(int locality)
197{
Julius Werner2f37bd62015-02-19 14:51:15 -0800198 u8 value = read8(TIS_REG(locality, TIS_REG_ACCESS));
Aaron Durbinc4220022013-07-24 16:02:14 -0500199 TPM_DEBUG_IO_READ(TIS_REG_ACCESS, value);
200 return value;
201}
202
203static inline void tpm_write_access(u8 data, int locality)
204{
205 TPM_DEBUG_IO_WRITE(TIS_REG_ACCESS, data);
Julius Werner2f37bd62015-02-19 14:51:15 -0800206 write8(TIS_REG(locality, TIS_REG_ACCESS), data);
Aaron Durbinc4220022013-07-24 16:02:14 -0500207}
208
209static inline u32 tpm_read_did_vid(int locality)
210{
Julius Werner2f37bd62015-02-19 14:51:15 -0800211 u32 value = read32(TIS_REG(locality, TIS_REG_DID_VID));
Aaron Durbinc4220022013-07-24 16:02:14 -0500212 TPM_DEBUG_IO_READ(TIS_REG_DID_VID, value);
213 return value;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700214}
215
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700216static inline void tpm_write_int_vector(int vector, int locality)
217{
218 TPM_DEBUG_IO_WRITE(TIS_REG_INT_VECTOR, vector);
Julius Werner2f37bd62015-02-19 14:51:15 -0800219 write8(TIS_REG(locality, TIS_REG_INT_VECTOR), vector & 0xf);
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700220}
221
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530222static inline u8 tpm_read_int_vector(int locality)
223{
224 u8 value = read8(TIS_REG(locality, TIS_REG_INT_VECTOR));
225 TPM_DEBUG_IO_READ(TIS_REG_INT_VECTOR, value);
226 return value;
227}
228
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700229static inline void tpm_write_int_polarity(int polarity, int locality)
230{
231 /* Set polarity and leave all other bits at 0 */
232 u32 value = (polarity & 0x3) << 3;
233 TPM_DEBUG_IO_WRITE(TIS_REG_INT_ENABLE, value);
Julius Werner2f37bd62015-02-19 14:51:15 -0800234 write32(TIS_REG(locality, TIS_REG_INT_ENABLE), value);
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700235}
236
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530237static inline u32 tpm_read_int_polarity(int locality)
238{
239 /* Get polarity and leave all other bits */
240 u32 value = read8(TIS_REG(locality, TIS_REG_INT_ENABLE));
241 value = (value >> 3) & 0x3;
242 TPM_DEBUG_IO_READ(TIS_REG_INT_ENABLE, value);
243 return value;
244}
245
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700246/*
Aaron Durbinc4220022013-07-24 16:02:14 -0500247 * tis_wait_sts()
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700248 *
Aaron Durbinc4220022013-07-24 16:02:14 -0500249 * Wait for at least a second for a status to change its state to match the
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700250 * expected state. Normally the transition happens within microseconds.
251 *
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700252 * @locality - locality
253 * @mask - bitmask for the bitfield(s) to watch
254 * @expected - value the field(s) are supposed to be set to
255 *
Aaron Durbinc4220022013-07-24 16:02:14 -0500256 * Returns 0 on success or TPM_TIMEOUT_ERR on timeout.
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700257 */
Aaron Durbinc4220022013-07-24 16:02:14 -0500258static int tis_wait_sts(int locality, u8 mask, u8 expected)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700259{
260 u32 time_us = MAX_DELAY_US;
261 while (time_us > 0) {
Aaron Durbinc4220022013-07-24 16:02:14 -0500262 u8 value = tpm_read_status(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700263 if ((value & mask) == expected)
Aaron Durbinc4220022013-07-24 16:02:14 -0500264 return 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700265 udelay(1); /* 1 us */
266 time_us--;
267 }
268 return TPM_TIMEOUT_ERR;
269}
270
Aaron Durbinc4220022013-07-24 16:02:14 -0500271static inline int tis_wait_ready(int locality)
272{
273 return tis_wait_sts(locality, TIS_STS_COMMAND_READY,
274 TIS_STS_COMMAND_READY);
275}
276
277static inline int tis_wait_valid(int locality)
278{
279 return tis_wait_sts(locality, TIS_STS_VALID, TIS_STS_VALID);
280}
281
282static inline int tis_wait_valid_data(int locality)
283{
284 const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID;
285 return tis_wait_sts(locality, has_data, has_data);
286}
287
288static inline int tis_has_valid_data(int locality)
289{
290 const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID;
291 return (tpm_read_status(locality) & has_data) == has_data;
292}
293
294static inline int tis_expect_data(int locality)
295{
296 return !!(tpm_read_status(locality) & TIS_STS_EXPECT);
297}
298
299/*
300 * tis_wait_access()
301 *
302 * Wait for at least a second for a access to change its state to match the
303 * expected state. Normally the transition happens within microseconds.
304 *
305 * @locality - locality
306 * @mask - bitmask for the bitfield(s) to watch
307 * @expected - value the field(s) are supposed to be set to
308 *
309 * Returns 0 on success or TPM_TIMEOUT_ERR on timeout.
310 */
311static int tis_wait_access(int locality, u8 mask, u8 expected)
312{
313 u32 time_us = MAX_DELAY_US;
314 while (time_us > 0) {
315 u8 value = tpm_read_access(locality);
316 if ((value & mask) == expected)
317 return 0;
318 udelay(1); /* 1 us */
319 time_us--;
320 }
321 return TPM_TIMEOUT_ERR;
322}
323
324static inline int tis_wait_dropped_access(int locality)
325{
326 return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY, 0);
327}
328
329static inline int tis_wait_received_access(int locality)
330{
331 return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY,
332 TIS_ACCESS_ACTIVE_LOCALITY);
333}
334
335static inline int tis_has_access(int locality)
336{
337 return !!(tpm_read_access(locality) & TIS_ACCESS_ACTIVE_LOCALITY);
338}
339
340static inline void tis_request_access(int locality)
341{
342 tpm_write_access(TIS_ACCESS_REQUEST_USE, locality);
343}
344
345static inline void tis_drop_access(int locality)
346{
347 tpm_write_access(TIS_ACCESS_ACTIVE_LOCALITY, locality);
348}
349
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700350/*
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700351 * PC Client Specific TPM Interface Specification section 11.2.12:
352 *
353 * Software must be prepared to send two writes of a "1" to command ready
354 * field: the first to indicate successful read of all the data, thus
355 * clearing the data from the ReadFIFO and freeing the TPM's resources,
356 * and the second to indicate to the TPM it is about to send a new command.
357 *
358 * In practice not all TPMs behave the same so it is necessary to be
359 * flexible when trying to set command ready.
360 *
361 * Returns 0 on success if the TPM is ready for transactions.
362 * Returns TPM_TIMEOUT_ERR if the command ready bit does not get set.
363 */
364static int tis_command_ready(u8 locality)
365{
366 u32 status;
367
368 /* 1st attempt to set command ready */
Aaron Durbinc4220022013-07-24 16:02:14 -0500369 tpm_write_status(TIS_STS_COMMAND_READY, locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700370
371 /* Wait for response */
Aaron Durbinc4220022013-07-24 16:02:14 -0500372 status = tpm_read_status(locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700373
374 /* Check if command ready is set yet */
375 if (status & TIS_STS_COMMAND_READY)
376 return 0;
377
378 /* 2nd attempt to set command ready */
Aaron Durbinc4220022013-07-24 16:02:14 -0500379 tpm_write_status(TIS_STS_COMMAND_READY, locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700380
Aaron Durbinc4220022013-07-24 16:02:14 -0500381 return tis_wait_ready(locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700382}
383
384/*
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700385 * Probe the TPM device and try determining its manufacturer/device name.
386 *
387 * Returns 0 on success (the device is found or was found during an earlier
388 * invocation) or TPM_DRIVER_ERR if the device is not found.
389 */
390static u32 tis_probe(void)
391{
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700392 const char *device_name = "unknown";
393 const char *vendor_name = device_name;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700394 const struct device_name *dev;
395 u32 didvid;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700396 u16 vid, did;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700397 int i;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700398
Aaron Durbincb997d32013-05-10 00:40:56 -0500399 if (car_get_var(vendor_dev_id))
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700400 return 0; /* Already probed. */
401
Aaron Durbinc4220022013-07-24 16:02:14 -0500402 didvid = tpm_read_did_vid(0);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700403 if (!didvid || (didvid == 0xffffffff)) {
404 printf("%s: No TPM device found\n", __FUNCTION__);
405 return TPM_DRIVER_ERR;
406 }
407
Aaron Durbincb997d32013-05-10 00:40:56 -0500408 car_set_var(vendor_dev_id, didvid);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700409
410 vid = didvid & 0xffff;
411 did = (didvid >> 16) & 0xffff;
412 for (i = 0; i < ARRAY_SIZE(vendor_names); i++) {
413 int j = 0;
414 u16 known_did;
415 if (vid == vendor_names[i].vendor_id) {
416 vendor_name = vendor_names[i].vendor_name;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700417 } else {
418 continue;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700419 }
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700420 dev = &vendor_names[i].dev_names[j];
421 while ((known_did = dev->dev_id) != 0xffff) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700422 if (known_did == did) {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700423 device_name = dev->dev_name;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700424 break;
425 }
426 j++;
Subrata41b08d92015-05-14 14:38:07 +0530427 dev = &vendor_names[i].dev_names[j];
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700428 }
429 break;
430 }
431 /* this will have to be converted into debug printout */
Duncan Laurie17ba9442015-09-03 16:00:49 -0700432 printk(BIOS_INFO, "Found TPM %s by %s\n", device_name, vendor_name);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700433 return 0;
434}
435
436/*
437 * tis_senddata()
438 *
439 * send the passed in data to the TPM device.
440 *
441 * @data - address of the data to send, byte by byte
442 * @len - length of the data to send
443 *
444 * Returns 0 on success, TPM_DRIVER_ERR on error (in case the device does
445 * not accept the entire command).
446 */
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +0200447static u32 tis_senddata(const u8 *const data, u32 len)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700448{
449 u32 offset = 0;
450 u16 burst = 0;
451 u32 max_cycles = 0;
452 u8 locality = 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700453
Aaron Durbinc4220022013-07-24 16:02:14 -0500454 if (tis_wait_ready(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700455 printf("%s:%d - failed to get 'command_ready' status\n",
456 __FILE__, __LINE__);
457 return TPM_DRIVER_ERR;
458 }
Aaron Durbinc4220022013-07-24 16:02:14 -0500459 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700460
461 while (1) {
462 unsigned count;
463
464 /* Wait till the device is ready to accept more data. */
465 while (!burst) {
466 if (max_cycles++ == MAX_DELAY_US) {
467 printf("%s:%d failed to feed %d bytes of %d\n",
468 __FILE__, __LINE__, len - offset, len);
469 return TPM_DRIVER_ERR;
470 }
471 udelay(1);
Aaron Durbinc4220022013-07-24 16:02:14 -0500472 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700473 }
474
475 max_cycles = 0;
476
477 /*
478 * Calculate number of bytes the TPM is ready to accept in one
479 * shot.
480 *
481 * We want to send the last byte outside of the loop (hence
482 * the -1 below) to make sure that the 'expected' status bit
483 * changes to zero exactly after the last byte is fed into the
484 * FIFO.
485 */
486 count = min(burst, len - offset - 1);
487 while (count--)
Aaron Durbinc4220022013-07-24 16:02:14 -0500488 tpm_write_data(data[offset++], locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700489
Aaron Durbinc4220022013-07-24 16:02:14 -0500490 if (tis_wait_valid(locality) || !tis_expect_data(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700491 printf("%s:%d TPM command feed overflow\n",
492 __FILE__, __LINE__);
493 return TPM_DRIVER_ERR;
494 }
495
Aaron Durbinc4220022013-07-24 16:02:14 -0500496 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700497 if ((offset == (len - 1)) && burst)
498 /*
499 * We need to be able to send the last byte to the
500 * device, so burst size must be nonzero before we
501 * break out.
502 */
503 break;
504 }
505
506 /* Send the last byte. */
Aaron Durbinc4220022013-07-24 16:02:14 -0500507 tpm_write_data(data[offset++], locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700508
509 /*
510 * Verify that TPM does not expect any more data as part of this
511 * command.
512 */
Aaron Durbinc4220022013-07-24 16:02:14 -0500513 if (tis_wait_valid(locality) || tis_expect_data(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700514 printf("%s:%d unexpected TPM status 0x%x\n",
Aaron Durbinc4220022013-07-24 16:02:14 -0500515 __FILE__, __LINE__, tpm_read_status(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700516 return TPM_DRIVER_ERR;
517 }
518
519 /* OK, sitting pretty, let's start the command execution. */
Aaron Durbinc4220022013-07-24 16:02:14 -0500520 tpm_write_status(TIS_STS_TPM_GO, locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700521
522 return 0;
523}
524
525/*
526 * tis_readresponse()
527 *
528 * read the TPM device response after a command was issued.
529 *
530 * @buffer - address where to read the response, byte by byte.
531 * @len - pointer to the size of buffer
532 *
533 * On success stores the number of received bytes to len and returns 0. On
534 * errors (misformatted TPM data or synchronization problems) returns
535 * TPM_DRIVER_ERR.
536 */
537static u32 tis_readresponse(u8 *buffer, size_t *len)
538{
539 u16 burst_count;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700540 u32 offset = 0;
541 u8 locality = 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700542 u32 expected_count = *len;
543 int max_cycles = 0;
544
545 /* Wait for the TPM to process the command */
Aaron Durbinc4220022013-07-24 16:02:14 -0500546 if (tis_wait_valid_data(locality)) {
547 printf("%s:%d failed processing command\n", __FILE__, __LINE__);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700548 return TPM_DRIVER_ERR;
549 }
550
551 do {
Aaron Durbinc4220022013-07-24 16:02:14 -0500552 while ((burst_count = tpm_read_burst_count(locality)) == 0) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700553 if (max_cycles++ == MAX_DELAY_US) {
554 printf("%s:%d TPM stuck on read\n",
555 __FILE__, __LINE__);
556 return TPM_DRIVER_ERR;
557 }
558 udelay(1);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700559 }
560
561 max_cycles = 0;
562
563 while (burst_count-- && (offset < expected_count)) {
Aaron Durbinc4220022013-07-24 16:02:14 -0500564 buffer[offset++] = tpm_read_data(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700565 if (offset == 6) {
566 /*
567 * We got the first six bytes of the reply,
568 * let's figure out how many bytes to expect
569 * total - it is stored as a 4 byte number in
570 * network order, starting with offset 2 into
571 * the body of the reply.
572 */
573 u32 real_length;
574 memcpy(&real_length,
575 buffer + 2,
576 sizeof(real_length));
577 expected_count = be32_to_cpu(real_length);
578
579 if ((expected_count < offset) ||
580 (expected_count > *len)) {
581 printf("%s:%d bad response size %d\n",
582 __FILE__, __LINE__,
583 expected_count);
584 return TPM_DRIVER_ERR;
585 }
586 }
587 }
588
589 /* Wait for the next portion */
Aaron Durbinc4220022013-07-24 16:02:14 -0500590 if (tis_wait_valid(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700591 printf("%s:%d failed to read response\n",
592 __FILE__, __LINE__);
593 return TPM_DRIVER_ERR;
594 }
595
596 if (offset == expected_count)
597 break; /* We got all we need */
598
Bill XIEa4bf0b72018-03-22 17:07:43 +0800599 /*
600 * Certain TPMs seem to need some delay between tis_wait_valid()
601 * and tis_has_valid_data(), or some race-condition-related
602 * issue will occur.
603 */
604 if (IS_ENABLED(CONFIG_TPM_RDRESP_NEED_DELAY))
605 udelay(10);
606
Aaron Durbinc4220022013-07-24 16:02:14 -0500607 } while (tis_has_valid_data(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700608
Aaron Durbinc4220022013-07-24 16:02:14 -0500609 /* * Make sure we indeed read all there was. */
610 if (tis_has_valid_data(locality)) {
611 printf("%s:%d wrong receive status: %x %d bytes left\n",
612 __FILE__, __LINE__, tpm_read_status(locality),
613 tpm_read_burst_count(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700614 return TPM_DRIVER_ERR;
615 }
616
617 /* Tell the TPM that we are done. */
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700618 if (tis_command_ready(locality) == TPM_TIMEOUT_ERR)
619 return TPM_DRIVER_ERR;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700620
621 *len = offset;
622 return 0;
623}
624
625/*
626 * tis_init()
627 *
628 * Initialize the TPM device. Returns 0 on success or TPM_DRIVER_ERR on
629 * failure (in case device probing did not succeed).
630 */
631int tis_init(void)
632{
633 if (tis_probe())
634 return TPM_DRIVER_ERR;
635 return 0;
636}
637
638/*
639 * tis_open()
640 *
641 * Requests access to locality 0 for the caller. After all commands have been
642 * completed the caller is supposed to call tis_close().
643 *
644 * Returns 0 on success, TPM_DRIVER_ERR on failure.
645 */
646int tis_open(void)
647{
648 u8 locality = 0; /* we use locality zero for everything */
649
650 if (tis_close())
651 return TPM_DRIVER_ERR;
652
653 /* now request access to locality */
Aaron Durbinc4220022013-07-24 16:02:14 -0500654 tis_request_access(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700655
656 /* did we get a lock? */
Aaron Durbinc4220022013-07-24 16:02:14 -0500657 if (tis_wait_received_access(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700658 printf("%s:%d - failed to lock locality %d\n",
659 __FILE__, __LINE__, locality);
660 return TPM_DRIVER_ERR;
661 }
662
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700663 /* Certain TPMs seem to need some delay here or they hang... */
664 udelay(10);
665
666 if (tis_command_ready(locality) == TPM_TIMEOUT_ERR)
667 return TPM_DRIVER_ERR;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700668
669 return 0;
670}
671
672/*
673 * tis_close()
674 *
Martin Roth56889792013-07-09 21:39:46 -0600675 * terminate the current session with the TPM by releasing the locked
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700676 * locality. Returns 0 on success of TPM_DRIVER_ERR on failure (in case lock
677 * removal did not succeed).
678 */
679int tis_close(void)
680{
681 u8 locality = 0;
Aaron Durbinc4220022013-07-24 16:02:14 -0500682 if (tis_has_access(locality)) {
683 tis_drop_access(locality);
684 if (tis_wait_dropped_access(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700685 printf("%s:%d - failed to release locality %d\n",
686 __FILE__, __LINE__, locality);
687 return TPM_DRIVER_ERR;
688 }
689 }
690 return 0;
691}
692
693/*
694 * tis_sendrecv()
695 *
696 * Send the requested data to the TPM and then try to get its response
697 *
698 * @sendbuf - buffer of the data to send
699 * @send_size size of the data to send
700 * @recvbuf - memory to save the response to
701 * @recv_len - pointer to the size of the response buffer
702 *
703 * Returns 0 on success (and places the number of response bytes at recv_len)
704 * or TPM_DRIVER_ERR on failure.
705 */
706int tis_sendrecv(const uint8_t *sendbuf, size_t send_size,
707 uint8_t *recvbuf, size_t *recv_len)
708{
709 if (tis_senddata(sendbuf, send_size)) {
710 printf("%s:%d failed sending data to TPM\n",
711 __FILE__, __LINE__);
712 return TPM_DRIVER_ERR;
713 }
714
715 return tis_readresponse(recvbuf, recv_len);
716}
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700717
718#ifdef __RAMSTAGE__
719
720/*
721 * tis_setup_interrupt()
722 *
723 * Set up the interrupt vector and polarity for locality 0 and
724 * disable all interrupts so they are unused in firmware but can
725 * be enabled by the OS.
726 *
727 * The values used here must match what is passed in the TPM ACPI
728 * device if ACPI is used on the platform.
729 *
730 * @vector - TPM interrupt vector
731 * @polarity - TPM interrupt polarity
732 *
733 * Returns 0 on success, TPM_DRIVER_ERR on failure.
734 */
735static int tis_setup_interrupt(int vector, int polarity)
736{
737 u8 locality = 0;
738 int has_access = tis_has_access(locality);
739
740 /* Open connection and request access if not already granted */
741 if (!has_access && tis_open() < 0)
742 return TPM_DRIVER_ERR;
743
744 /* Set TPM interrupt vector */
745 tpm_write_int_vector(vector, locality);
746
Elyes HAOUAS18958382018-08-07 12:23:16 +0200747 /* Set TPM interrupt polarity and disable interrupts */
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700748 tpm_write_int_polarity(polarity, locality);
749
750 /* Close connection if it was opened */
751 if (!has_access && tis_close() < 0)
752 return TPM_DRIVER_ERR;
753
754 return 0;
755}
756
757static void lpc_tpm_read_resources(struct device *dev)
758{
759 /* Static 5K memory region specified in Kconfig */
760 mmio_resource(dev, 0, CONFIG_TPM_TIS_BASE_ADDRESS >> 10, 0x5000 >> 10);
761}
762
763static void lpc_tpm_set_resources(struct device *dev)
764{
765 tpm_config_t *config = (tpm_config_t *)dev->chip_info;
766 struct resource *res;
767
768 for (res = dev->resource_list; res; res = res->next) {
769 if (!(res->flags & IORESOURCE_ASSIGNED))
770 continue;
771
772 if (res->flags & IORESOURCE_IRQ) {
773 /* Set interrupt vector */
774 tis_setup_interrupt((int)res->base,
775 config->irq_polarity);
776 } else {
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700777 continue;
778 }
779
780 res->flags |= IORESOURCE_STORED;
781 report_resource_stored(dev, res, " <tpm>");
782 }
783}
784
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530785#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
786
787static void tpm_ppi_func0_cb(void *arg)
788{
789 /* Functions 1-8. */
790 u8 buf[] = {0xff, 0x01};
791 acpigen_write_return_byte_buffer(buf, 2);
792}
793
794static void tpm_ppi_func1_cb(void *arg)
795{
796 if (IS_ENABLED(CONFIG_TPM2))
797 /* Interface version: 2.0 */
798 acpigen_write_return_string("2.0");
799 else
800 /* Interface version: 1.2 */
801 acpigen_write_return_string("1.2");
802}
803
804static void tpm_ppi_func2_cb(void *arg)
805{
806 /* Submit operations: drop on the floor and return success. */
807 acpigen_write_return_byte(0);
808}
809
810static void tpm_ppi_func3_cb(void *arg)
811{
812 /* Pending operation: none. */
813 acpigen_emit_byte(RETURN_OP);
814 acpigen_write_package(2);
815 acpigen_write_byte(0);
816 acpigen_write_byte(0);
817 acpigen_pop_len();
818}
819static void tpm_ppi_func4_cb(void *arg)
820{
821 /* Pre-OS transition method: reboot. */
822 acpigen_write_return_byte(2);
823}
824static void tpm_ppi_func5_cb(void *arg)
825{
826 /* Operation response: no operation executed. */
827 acpigen_emit_byte(RETURN_OP);
828 acpigen_write_package(3);
829 acpigen_write_byte(0);
830 acpigen_write_byte(0);
831 acpigen_write_byte(0);
832 acpigen_pop_len();
833}
834static void tpm_ppi_func6_cb(void *arg)
835{
836 /*
837 * Set preferred user language: deprecated and must return 3 aka
838 * "not implemented".
839 */
840 acpigen_write_return_byte(3);
841}
842static void tpm_ppi_func7_cb(void *arg)
843{
844 /* Submit operations: deny. */
845 acpigen_write_return_byte(3);
846}
847static void tpm_ppi_func8_cb(void *arg)
848{
849 /* All actions are forbidden. */
850 acpigen_write_return_byte(1);
851}
852static void (*tpm_ppi_callbacks[])(void *) = {
853 tpm_ppi_func0_cb,
854 tpm_ppi_func1_cb,
855 tpm_ppi_func2_cb,
856 tpm_ppi_func3_cb,
857 tpm_ppi_func4_cb,
858 tpm_ppi_func5_cb,
859 tpm_ppi_func6_cb,
860 tpm_ppi_func7_cb,
861 tpm_ppi_func8_cb,
862};
863
864static void tpm_mci_func0_cb(void *arg)
865{
866 /* Function 1. */
867 acpigen_write_return_singleton_buffer(0x3);
868}
869static void tpm_mci_func1_cb(void *arg)
870{
871 /* Just return success. */
872 acpigen_write_return_byte(0);
873}
874
875static void (*tpm_mci_callbacks[])(void *) = {
876 tpm_mci_func0_cb,
877 tpm_mci_func1_cb,
878};
879
880static void lpc_tpm_fill_ssdt(struct device *dev)
881{
882 const char *path = acpi_device_path(dev->bus->dev);
883 u32 arg;
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530884
Philipp Deppenwiese3a1fbea2016-12-14 01:06:55 +0100885 if (!path) {
Tobias Diedrich36537f12017-02-10 00:28:45 +0100886 path = "\\_SB_.PCI0.LPCB";
Philipp Deppenwiese3a1fbea2016-12-14 01:06:55 +0100887 printk(BIOS_DEBUG, "Using default TPM ACPI path: '%s'\n", path);
888 }
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530889
890 /* Device */
891 acpigen_write_scope(path);
892 acpigen_write_device(acpi_device_name(dev));
893
894 acpigen_write_name("_HID");
895 acpigen_emit_eisaid("PNP0C31");
896
897 acpigen_write_name("_CID");
898 acpigen_emit_eisaid("PNP0C31");
899
900 acpigen_write_name_integer("_UID", 1);
901
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530902 u32 did_vid = tpm_read_did_vid(0);
903 if (did_vid > 0 && did_vid < 0xffffffff)
904 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
905 else
906 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_OFF);
907
Kevin Cody-Littlec97b5af2018-05-09 14:14:59 -0400908 u16 port = dev->path.pnp.port;
909
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530910 /* Resources */
911 acpigen_write_name("_CRS");
912 acpigen_write_resourcetemplate_header();
913 acpigen_write_mem32fixed(1, CONFIG_TPM_TIS_BASE_ADDRESS, 0x5000);
Kevin Cody-Littlec97b5af2018-05-09 14:14:59 -0400914 acpigen_write_io16(port, port, 1, 2, 1);
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530915
916 if (CONFIG_TPM_PIRQ) {
917 /*
918 * PIRQ: Update interrupt vector with configured PIRQ
919 * Active-Low Level-Triggered Shared
920 */
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800921 struct acpi_irq tpm_irq_a = ACPI_IRQ_LEVEL_LOW(CONFIG_TPM_PIRQ);
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530922 acpi_device_write_interrupt(&tpm_irq_a);
923 } else if (tpm_read_int_vector(0) > 0) {
924 u8 int_vec = tpm_read_int_vector(0);
925 u8 int_pol = tpm_read_int_polarity(0);
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800926 struct acpi_irq tpm_irq = ACPI_IRQ_LEVEL_LOW(int_vec);
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530927
928 if (int_pol & 1)
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800929 tpm_irq.polarity = ACPI_IRQ_ACTIVE_LOW;
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530930 else
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800931 tpm_irq.polarity = ACPI_IRQ_ACTIVE_HIGH;
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530932
933 if (int_pol & 2)
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800934 tpm_irq.mode = ACPI_IRQ_EDGE_TRIGGERED;
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530935 else
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800936 tpm_irq.mode = ACPI_IRQ_LEVEL_TRIGGERED;
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530937
938 acpi_device_write_interrupt(&tpm_irq);
939 }
940
941 acpigen_write_resourcetemplate_footer();
942
943 if (!IS_ENABLED(CONFIG_CHROMEOS)) {
944 /*
945 * _DSM method
946 */
947 struct dsm_uuid ids[] = {
948 /* Physical presence interface.
949 * This is used to submit commands like "Clear TPM" to
950 * be run at next reboot provided that user confirms
951 * them. Spec allows user to cancel all commands and/or
952 * configure BIOS to reject commands. So we pretend that
953 * user did just this: cancelled everything. If user
954 * really wants to clear TPM the only option now is to
955 * do it manually in payload.
956 */
957 DSM_UUID(TPM_PPI_UUID, &tpm_ppi_callbacks[0],
958 ARRAY_SIZE(tpm_ppi_callbacks), (void *) &arg),
959 /* Memory clearing on boot: just a dummy. */
960 DSM_UUID(TPM_MCI_UUID, &tpm_mci_callbacks[0],
961 ARRAY_SIZE(tpm_mci_callbacks), (void *) &arg),
962 };
963
964 acpigen_write_dsm_uuid_arr(ids, ARRAY_SIZE(ids));
965 }
966 acpigen_pop_len(); /* Device */
967 acpigen_pop_len(); /* Scope */
968
969 printk(BIOS_INFO, "%s.%s: %s %s\n", path, acpi_device_name(dev),
970 dev->chip_ops->name, dev_path(dev));
971}
972
Aaron Durbinaa090cb2017-09-13 16:01:52 -0600973static const char *lpc_tpm_acpi_name(const struct device *dev)
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530974{
975 return "TPM";
976}
977#endif
978
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700979static struct device_operations lpc_tpm_ops = {
980 .read_resources = &lpc_tpm_read_resources,
981 .set_resources = &lpc_tpm_set_resources,
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530982#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
983 .acpi_name = &lpc_tpm_acpi_name,
984 .acpi_fill_ssdt_generator = &lpc_tpm_fill_ssdt,
985#endif
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700986};
987
988static struct pnp_info pnp_dev_info[] = {
989 { .flags = PNP_IRQ0 }
990};
991
992static void enable_dev(struct device *dev)
993{
994 pnp_enable_devices(dev, &lpc_tpm_ops,
995 ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
996}
997
998struct chip_operations drivers_pc80_tpm_ops = {
999 CHIP_NAME("LPC TPM")
1000 .enable_dev = enable_dev
1001};
1002
1003#endif /* __RAMSTAGE__ */