blob: 2b29acfaa90a32955da5a1bb86663d2a0d3685b6 [file] [log] [blame]
Angel Pons8a3453f2020-04-02 23:48:19 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Stefan Reinauer3008bbad2011-10-11 14:46:25 -07002
3/*
4 * The code in this file has been heavily based on the article "Writing a TPM
5 * Device Driver" published on http://ptgmedia.pearsoncmg.com and the
6 * submission by Stefan Berger on Qemu-devel mailing list.
7 *
8 * One principal difference is that in the simplest config the other than 0
9 * TPM localities do not get mapped by some devices (for instance, by
10 * Infineon slb9635), so this driver provides access to locality 0 only.
11 */
12
Elyes HAOUAS361a9352019-12-18 21:26:33 +010013#include <commonlib/helpers.h>
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070014#include <string.h>
15#include <delay.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020016#include <device/mmio.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -070017#include <acpi/acpi.h>
18#include <acpi/acpigen.h>
19#include <acpi/acpi_device.h>
Naresh G Solanki80ff0382016-11-15 11:01:33 +053020#include <device/device.h>
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070021#include <console/console.h>
Philipp Deppenwiesed88fb362017-10-18 20:26:18 +020022#include <security/tpm/tis.h>
Duncan Lauriedd281ed2014-10-30 15:20:19 -070023#include <device/pnp.h>
Patrick Rudolphd8d8be12020-09-21 09:48:53 +020024#include <drivers/tpm/tpm_ppi.h>
Duncan Lauriedd281ed2014-10-30 15:20:19 -070025#include "chip.h"
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070026
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070027#define PREFIX "lpc_tpm: "
Patrick Rudolphd8d8be12020-09-21 09:48:53 +020028
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070029/* coreboot wrapper for TPM driver (start) */
30#define TPM_DEBUG(fmt, args...) \
Julius Wernercd49cce2019-03-05 16:53:33 -080031 if (CONFIG(DEBUG_TPM)) { \
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070032 printk(BIOS_DEBUG, PREFIX); \
Elyes HAOUASa342f392018-10-17 10:56:26 +020033 printk(BIOS_DEBUG, fmt, ##args); \
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070034 }
Aaron Durbinc4220022013-07-24 16:02:14 -050035#define TPM_DEBUG_IO_READ(reg_, val_) \
36 TPM_DEBUG("Read reg 0x%x returns 0x%x\n", (reg_), (val_))
37#define TPM_DEBUG_IO_WRITE(reg_, val_) \
38 TPM_DEBUG("Write reg 0x%x with 0x%x\n", (reg_), (val_))
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070039#define printf(x...) printk(BIOS_ERR, x)
40
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070041/* coreboot wrapper for TPM driver (end) */
42
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070043/* the macro accepts the locality value, but only locality 0 is operational */
44#define TIS_REG(LOCALITY, REG) \
Patrick Rudolph56fdafb2020-07-01 20:07:08 +020045 (void *)(uintptr_t)(CONFIG_TPM_TIS_BASE_ADDRESS + (LOCALITY << 12) + REG)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070046
47/* hardware registers' offsets */
48#define TIS_REG_ACCESS 0x0
49#define TIS_REG_INT_ENABLE 0x8
50#define TIS_REG_INT_VECTOR 0xc
51#define TIS_REG_INT_STATUS 0x10
52#define TIS_REG_INTF_CAPABILITY 0x14
53#define TIS_REG_STS 0x18
Aaron Durbinc4220022013-07-24 16:02:14 -050054#define TIS_REG_BURST_COUNT 0x19
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070055#define TIS_REG_DATA_FIFO 0x24
56#define TIS_REG_DID_VID 0xf00
57#define TIS_REG_RID 0xf04
58
59/* Some registers' bit field definitions */
60#define TIS_STS_VALID (1 << 7) /* 0x80 */
61#define TIS_STS_COMMAND_READY (1 << 6) /* 0x40 */
62#define TIS_STS_TPM_GO (1 << 5) /* 0x20 */
63#define TIS_STS_DATA_AVAILABLE (1 << 4) /* 0x10 */
64#define TIS_STS_EXPECT (1 << 3) /* 0x08 */
65#define TIS_STS_RESPONSE_RETRY (1 << 1) /* 0x02 */
66
67#define TIS_ACCESS_TPM_REG_VALID_STS (1 << 7) /* 0x80 */
68#define TIS_ACCESS_ACTIVE_LOCALITY (1 << 5) /* 0x20 */
69#define TIS_ACCESS_BEEN_SEIZED (1 << 4) /* 0x10 */
70#define TIS_ACCESS_SEIZE (1 << 3) /* 0x08 */
71#define TIS_ACCESS_PENDING_REQUEST (1 << 2) /* 0x04 */
72#define TIS_ACCESS_REQUEST_USE (1 << 1) /* 0x02 */
73#define TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0) /* 0x01 */
74
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070075/*
76 * Error value returned if a tpm register does not enter the expected state
77 * after continuous polling. No actual TPM register reading ever returns ~0,
78 * so this value is a safe error indication to be mixed with possible status
79 * register values.
80 */
81#define TPM_TIMEOUT_ERR (~0)
82
83/* Error value returned on various TPM driver errors */
84#define TPM_DRIVER_ERR (~0)
85
86 /* 1 second is plenty for anything TPM does.*/
87#define MAX_DELAY_US (1000 * 1000)
88
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070089/*
90 * Structures defined below allow creating descriptions of TPM vendor/device
91 * ID information for run time discovery. The only device the system knows
92 * about at this time is Infineon slb9635
93 */
94struct device_name {
95 u16 dev_id;
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +020096 const char *const dev_name;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070097};
98
99struct vendor_name {
100 u16 vendor_id;
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +0200101 const char *vendor_name;
102 const struct device_name *dev_names;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700103};
104
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700105static const struct device_name atmel_devices[] = {
106 {0x3204, "AT97SC3204"},
107 {0xffff}
108};
109
Stefan Reinauerc668af72011-10-27 21:28:25 +0000110static const struct device_name infineon_devices[] = {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700111 {0x000b, "SLB9635 TT 1.2"},
Julius Wernercd49cce2019-03-05 16:53:33 -0800112#if CONFIG(TPM2)
Kamil Wcislobf5ccfd2017-10-12 13:12:11 +0200113 {0x001a, "SLB9665 TT 2.0"},
Subrata Banik5b8c4a72016-11-11 09:28:45 +0530114 {0x001b, "SLB9670 TT 2.0"},
115#else
Kamil Wcislobf5ccfd2017-10-12 13:12:11 +0200116 {0x001a, "SLB9660 TT 1.2"},
Wenkai Du641529b2015-05-29 10:54:27 -0700117 {0x001b, "SLB9670 TT 1.2"},
Subrata Banik5b8c4a72016-11-11 09:28:45 +0530118#endif
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700119 {0xffff}
120};
121
122static const struct device_name nuvoton_devices[] = {
123 {0x00fe, "NPCT420AA V2"},
124 {0xffff}
125};
126
127static const struct device_name stmicro_devices[] = {
128 {0x0000, "ST33ZP24" },
129 {0xffff}
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700130};
131
Tsung Ho Wu804a0432019-06-07 15:03:49 -0700132static const struct device_name swtpm_devices[] = {
133#if CONFIG(TPM2)
134 {0x0001, "SwTPM 2.0" },
135#endif
136 {0xffff}
137};
138
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700139static const struct vendor_name vendor_names[] = {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700140 {0x1114, "Atmel", atmel_devices},
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700141 {0x15d1, "Infineon", infineon_devices},
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700142 {0x1050, "Nuvoton", nuvoton_devices},
Tsung Ho Wu804a0432019-06-07 15:03:49 -0700143 {0x1014, "TPM Emulator", swtpm_devices},
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700144 {0x104a, "ST Microelectronics", stmicro_devices},
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700145};
146
147/*
148 * Cached vendor/device ID pair to indicate that the device has been already
149 * discovered
150 */
Arthur Heymans0ca944b2019-11-20 19:51:06 +0100151static u32 vendor_dev_id;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700152
Aaron Durbinc4220022013-07-24 16:02:14 -0500153static inline u8 tpm_read_status(int locality)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700154{
Julius Werner2f37bd62015-02-19 14:51:15 -0800155 u8 value = read8(TIS_REG(locality, TIS_REG_STS));
Aaron Durbinc4220022013-07-24 16:02:14 -0500156 TPM_DEBUG_IO_READ(TIS_REG_STS, value);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700157 return value;
158}
159
Aaron Durbinc4220022013-07-24 16:02:14 -0500160static inline void tpm_write_status(u8 sts, int locality)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700161{
Aaron Durbinc4220022013-07-24 16:02:14 -0500162 TPM_DEBUG_IO_WRITE(TIS_REG_STS, sts);
Julius Werner2f37bd62015-02-19 14:51:15 -0800163 write8(TIS_REG(locality, TIS_REG_STS), sts);
Aaron Durbinc4220022013-07-24 16:02:14 -0500164}
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700165
Aaron Durbinc4220022013-07-24 16:02:14 -0500166static inline u8 tpm_read_data(int locality)
167{
Julius Werner2f37bd62015-02-19 14:51:15 -0800168 u8 value = read8(TIS_REG(locality, TIS_REG_DATA_FIFO));
Aaron Durbinc4220022013-07-24 16:02:14 -0500169 TPM_DEBUG_IO_READ(TIS_REG_DATA_FIFO, value);
170 return value;
171}
172
173static inline void tpm_write_data(u8 data, int locality)
174{
Werner Zeha31d6cd2021-10-07 07:15:38 +0200175 TPM_DEBUG_IO_WRITE(TIS_REG_DATA_FIFO, data);
Julius Werner2f37bd62015-02-19 14:51:15 -0800176 write8(TIS_REG(locality, TIS_REG_DATA_FIFO), data);
Aaron Durbinc4220022013-07-24 16:02:14 -0500177}
178
179static inline u16 tpm_read_burst_count(int locality)
180{
181 u16 count;
Julius Werner2f37bd62015-02-19 14:51:15 -0800182 count = read8(TIS_REG(locality, TIS_REG_BURST_COUNT));
183 count |= read8(TIS_REG(locality, TIS_REG_BURST_COUNT + 1)) << 8;
Aaron Durbinc4220022013-07-24 16:02:14 -0500184 TPM_DEBUG_IO_READ(TIS_REG_BURST_COUNT, count);
185 return count;
186}
187
188static inline u8 tpm_read_access(int locality)
189{
Julius Werner2f37bd62015-02-19 14:51:15 -0800190 u8 value = read8(TIS_REG(locality, TIS_REG_ACCESS));
Aaron Durbinc4220022013-07-24 16:02:14 -0500191 TPM_DEBUG_IO_READ(TIS_REG_ACCESS, value);
192 return value;
193}
194
195static inline void tpm_write_access(u8 data, int locality)
196{
197 TPM_DEBUG_IO_WRITE(TIS_REG_ACCESS, data);
Julius Werner2f37bd62015-02-19 14:51:15 -0800198 write8(TIS_REG(locality, TIS_REG_ACCESS), data);
Aaron Durbinc4220022013-07-24 16:02:14 -0500199}
200
201static inline u32 tpm_read_did_vid(int locality)
202{
Julius Werner2f37bd62015-02-19 14:51:15 -0800203 u32 value = read32(TIS_REG(locality, TIS_REG_DID_VID));
Aaron Durbinc4220022013-07-24 16:02:14 -0500204 TPM_DEBUG_IO_READ(TIS_REG_DID_VID, value);
205 return value;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700206}
207
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700208static inline void tpm_write_int_vector(int vector, int locality)
209{
210 TPM_DEBUG_IO_WRITE(TIS_REG_INT_VECTOR, vector);
Julius Werner2f37bd62015-02-19 14:51:15 -0800211 write8(TIS_REG(locality, TIS_REG_INT_VECTOR), vector & 0xf);
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700212}
213
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530214static inline u8 tpm_read_int_vector(int locality)
215{
216 u8 value = read8(TIS_REG(locality, TIS_REG_INT_VECTOR));
217 TPM_DEBUG_IO_READ(TIS_REG_INT_VECTOR, value);
218 return value;
219}
220
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700221static inline void tpm_write_int_polarity(int polarity, int locality)
222{
223 /* Set polarity and leave all other bits at 0 */
224 u32 value = (polarity & 0x3) << 3;
225 TPM_DEBUG_IO_WRITE(TIS_REG_INT_ENABLE, value);
Julius Werner2f37bd62015-02-19 14:51:15 -0800226 write32(TIS_REG(locality, TIS_REG_INT_ENABLE), value);
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700227}
228
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530229static inline u32 tpm_read_int_polarity(int locality)
230{
231 /* Get polarity and leave all other bits */
232 u32 value = read8(TIS_REG(locality, TIS_REG_INT_ENABLE));
233 value = (value >> 3) & 0x3;
234 TPM_DEBUG_IO_READ(TIS_REG_INT_ENABLE, value);
235 return value;
236}
237
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700238/*
Aaron Durbinc4220022013-07-24 16:02:14 -0500239 * tis_wait_sts()
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700240 *
Aaron Durbinc4220022013-07-24 16:02:14 -0500241 * Wait for at least a second for a status to change its state to match the
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700242 * expected state. Normally the transition happens within microseconds.
243 *
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700244 * @locality - locality
245 * @mask - bitmask for the bitfield(s) to watch
246 * @expected - value the field(s) are supposed to be set to
247 *
Aaron Durbinc4220022013-07-24 16:02:14 -0500248 * Returns 0 on success or TPM_TIMEOUT_ERR on timeout.
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700249 */
Aaron Durbinc4220022013-07-24 16:02:14 -0500250static int tis_wait_sts(int locality, u8 mask, u8 expected)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700251{
252 u32 time_us = MAX_DELAY_US;
253 while (time_us > 0) {
Aaron Durbinc4220022013-07-24 16:02:14 -0500254 u8 value = tpm_read_status(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700255 if ((value & mask) == expected)
Aaron Durbinc4220022013-07-24 16:02:14 -0500256 return 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700257 udelay(1); /* 1 us */
258 time_us--;
259 }
260 return TPM_TIMEOUT_ERR;
261}
262
Aaron Durbinc4220022013-07-24 16:02:14 -0500263static inline int tis_wait_ready(int locality)
264{
265 return tis_wait_sts(locality, TIS_STS_COMMAND_READY,
266 TIS_STS_COMMAND_READY);
267}
268
269static inline int tis_wait_valid(int locality)
270{
271 return tis_wait_sts(locality, TIS_STS_VALID, TIS_STS_VALID);
272}
273
274static inline int tis_wait_valid_data(int locality)
275{
276 const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID;
277 return tis_wait_sts(locality, has_data, has_data);
278}
279
280static inline int tis_has_valid_data(int locality)
281{
282 const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID;
283 return (tpm_read_status(locality) & has_data) == has_data;
284}
285
286static inline int tis_expect_data(int locality)
287{
288 return !!(tpm_read_status(locality) & TIS_STS_EXPECT);
289}
290
291/*
292 * tis_wait_access()
293 *
294 * Wait for at least a second for a access to change its state to match the
295 * expected state. Normally the transition happens within microseconds.
296 *
297 * @locality - locality
298 * @mask - bitmask for the bitfield(s) to watch
299 * @expected - value the field(s) are supposed to be set to
300 *
301 * Returns 0 on success or TPM_TIMEOUT_ERR on timeout.
302 */
303static int tis_wait_access(int locality, u8 mask, u8 expected)
304{
305 u32 time_us = MAX_DELAY_US;
306 while (time_us > 0) {
307 u8 value = tpm_read_access(locality);
308 if ((value & mask) == expected)
309 return 0;
310 udelay(1); /* 1 us */
311 time_us--;
312 }
313 return TPM_TIMEOUT_ERR;
314}
315
316static inline int tis_wait_dropped_access(int locality)
317{
318 return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY, 0);
319}
320
321static inline int tis_wait_received_access(int locality)
322{
323 return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY,
324 TIS_ACCESS_ACTIVE_LOCALITY);
325}
326
327static inline int tis_has_access(int locality)
328{
329 return !!(tpm_read_access(locality) & TIS_ACCESS_ACTIVE_LOCALITY);
330}
331
332static inline void tis_request_access(int locality)
333{
334 tpm_write_access(TIS_ACCESS_REQUEST_USE, locality);
335}
336
337static inline void tis_drop_access(int locality)
338{
339 tpm_write_access(TIS_ACCESS_ACTIVE_LOCALITY, locality);
340}
341
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700342/*
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700343 * PC Client Specific TPM Interface Specification section 11.2.12:
344 *
345 * Software must be prepared to send two writes of a "1" to command ready
346 * field: the first to indicate successful read of all the data, thus
347 * clearing the data from the ReadFIFO and freeing the TPM's resources,
348 * and the second to indicate to the TPM it is about to send a new command.
349 *
350 * In practice not all TPMs behave the same so it is necessary to be
351 * flexible when trying to set command ready.
352 *
353 * Returns 0 on success if the TPM is ready for transactions.
354 * Returns TPM_TIMEOUT_ERR if the command ready bit does not get set.
355 */
356static int tis_command_ready(u8 locality)
357{
358 u32 status;
359
360 /* 1st attempt to set command ready */
Aaron Durbinc4220022013-07-24 16:02:14 -0500361 tpm_write_status(TIS_STS_COMMAND_READY, locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700362
363 /* Wait for response */
Aaron Durbinc4220022013-07-24 16:02:14 -0500364 status = tpm_read_status(locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700365
366 /* Check if command ready is set yet */
367 if (status & TIS_STS_COMMAND_READY)
368 return 0;
369
370 /* 2nd attempt to set command ready */
Aaron Durbinc4220022013-07-24 16:02:14 -0500371 tpm_write_status(TIS_STS_COMMAND_READY, locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700372
Aaron Durbinc4220022013-07-24 16:02:14 -0500373 return tis_wait_ready(locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700374}
375
376/*
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700377 * Probe the TPM device and try determining its manufacturer/device name.
378 *
379 * Returns 0 on success (the device is found or was found during an earlier
380 * invocation) or TPM_DRIVER_ERR if the device is not found.
381 */
382static u32 tis_probe(void)
383{
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700384 const char *device_name = "unknown";
385 const char *vendor_name = device_name;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700386 const struct device_name *dev;
387 u32 didvid;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700388 u16 vid, did;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700389 int i;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700390
Arthur Heymans0ca944b2019-11-20 19:51:06 +0100391 if (vendor_dev_id)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700392 return 0; /* Already probed. */
393
Aaron Durbinc4220022013-07-24 16:02:14 -0500394 didvid = tpm_read_did_vid(0);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700395 if (!didvid || (didvid == 0xffffffff)) {
Angel Pons08e8cab2020-06-18 15:20:37 +0200396 printf("%s: No TPM device found\n", __func__);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700397 return TPM_DRIVER_ERR;
398 }
399
Arthur Heymans0ca944b2019-11-20 19:51:06 +0100400 vendor_dev_id = didvid;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700401
402 vid = didvid & 0xffff;
403 did = (didvid >> 16) & 0xffff;
404 for (i = 0; i < ARRAY_SIZE(vendor_names); i++) {
405 int j = 0;
406 u16 known_did;
407 if (vid == vendor_names[i].vendor_id) {
408 vendor_name = vendor_names[i].vendor_name;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700409 } else {
410 continue;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700411 }
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700412 dev = &vendor_names[i].dev_names[j];
413 while ((known_did = dev->dev_id) != 0xffff) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700414 if (known_did == did) {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700415 device_name = dev->dev_name;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700416 break;
417 }
418 j++;
Subrata41b08d92015-05-14 14:38:07 +0530419 dev = &vendor_names[i].dev_names[j];
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700420 }
421 break;
422 }
423 /* this will have to be converted into debug printout */
Duncan Laurie17ba9442015-09-03 16:00:49 -0700424 printk(BIOS_INFO, "Found TPM %s by %s\n", device_name, vendor_name);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700425 return 0;
426}
427
428/*
429 * tis_senddata()
430 *
431 * send the passed in data to the TPM device.
432 *
433 * @data - address of the data to send, byte by byte
434 * @len - length of the data to send
435 *
436 * Returns 0 on success, TPM_DRIVER_ERR on error (in case the device does
437 * not accept the entire command).
438 */
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +0200439static u32 tis_senddata(const u8 *const data, u32 len)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700440{
441 u32 offset = 0;
442 u16 burst = 0;
443 u32 max_cycles = 0;
444 u8 locality = 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700445
Aaron Durbinc4220022013-07-24 16:02:14 -0500446 if (tis_wait_ready(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700447 printf("%s:%d - failed to get 'command_ready' status\n",
448 __FILE__, __LINE__);
449 return TPM_DRIVER_ERR;
450 }
Aaron Durbinc4220022013-07-24 16:02:14 -0500451 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700452
453 while (1) {
Martin Roth38ddbfb2019-10-23 21:41:00 -0600454 unsigned int count;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700455
456 /* Wait till the device is ready to accept more data. */
457 while (!burst) {
458 if (max_cycles++ == MAX_DELAY_US) {
459 printf("%s:%d failed to feed %d bytes of %d\n",
460 __FILE__, __LINE__, len - offset, len);
461 return TPM_DRIVER_ERR;
462 }
463 udelay(1);
Aaron Durbinc4220022013-07-24 16:02:14 -0500464 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700465 }
466
467 max_cycles = 0;
468
469 /*
470 * Calculate number of bytes the TPM is ready to accept in one
471 * shot.
472 *
473 * We want to send the last byte outside of the loop (hence
474 * the -1 below) to make sure that the 'expected' status bit
475 * changes to zero exactly after the last byte is fed into the
476 * FIFO.
477 */
Elyes HAOUAS361a9352019-12-18 21:26:33 +0100478 count = MIN(burst, len - offset - 1);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700479 while (count--)
Aaron Durbinc4220022013-07-24 16:02:14 -0500480 tpm_write_data(data[offset++], locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700481
Aaron Durbinc4220022013-07-24 16:02:14 -0500482 if (tis_wait_valid(locality) || !tis_expect_data(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700483 printf("%s:%d TPM command feed overflow\n",
484 __FILE__, __LINE__);
485 return TPM_DRIVER_ERR;
486 }
487
Aaron Durbinc4220022013-07-24 16:02:14 -0500488 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700489 if ((offset == (len - 1)) && burst)
490 /*
491 * We need to be able to send the last byte to the
492 * device, so burst size must be nonzero before we
493 * break out.
494 */
495 break;
496 }
497
498 /* Send the last byte. */
Aaron Durbinc4220022013-07-24 16:02:14 -0500499 tpm_write_data(data[offset++], locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700500
501 /*
502 * Verify that TPM does not expect any more data as part of this
503 * command.
504 */
Aaron Durbinc4220022013-07-24 16:02:14 -0500505 if (tis_wait_valid(locality) || tis_expect_data(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700506 printf("%s:%d unexpected TPM status 0x%x\n",
Aaron Durbinc4220022013-07-24 16:02:14 -0500507 __FILE__, __LINE__, tpm_read_status(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700508 return TPM_DRIVER_ERR;
509 }
510
511 /* OK, sitting pretty, let's start the command execution. */
Aaron Durbinc4220022013-07-24 16:02:14 -0500512 tpm_write_status(TIS_STS_TPM_GO, locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700513
514 return 0;
515}
516
517/*
518 * tis_readresponse()
519 *
520 * read the TPM device response after a command was issued.
521 *
522 * @buffer - address where to read the response, byte by byte.
523 * @len - pointer to the size of buffer
524 *
525 * On success stores the number of received bytes to len and returns 0. On
526 * errors (misformatted TPM data or synchronization problems) returns
527 * TPM_DRIVER_ERR.
528 */
529static u32 tis_readresponse(u8 *buffer, size_t *len)
530{
531 u16 burst_count;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700532 u32 offset = 0;
533 u8 locality = 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700534 u32 expected_count = *len;
535 int max_cycles = 0;
536
537 /* Wait for the TPM to process the command */
Aaron Durbinc4220022013-07-24 16:02:14 -0500538 if (tis_wait_valid_data(locality)) {
539 printf("%s:%d failed processing command\n", __FILE__, __LINE__);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700540 return TPM_DRIVER_ERR;
541 }
542
543 do {
Aaron Durbinc4220022013-07-24 16:02:14 -0500544 while ((burst_count = tpm_read_burst_count(locality)) == 0) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700545 if (max_cycles++ == MAX_DELAY_US) {
546 printf("%s:%d TPM stuck on read\n",
547 __FILE__, __LINE__);
548 return TPM_DRIVER_ERR;
549 }
550 udelay(1);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700551 }
552
553 max_cycles = 0;
554
555 while (burst_count-- && (offset < expected_count)) {
Aaron Durbinc4220022013-07-24 16:02:14 -0500556 buffer[offset++] = tpm_read_data(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700557 if (offset == 6) {
558 /*
559 * We got the first six bytes of the reply,
560 * let's figure out how many bytes to expect
561 * total - it is stored as a 4 byte number in
562 * network order, starting with offset 2 into
563 * the body of the reply.
564 */
565 u32 real_length;
566 memcpy(&real_length,
567 buffer + 2,
568 sizeof(real_length));
569 expected_count = be32_to_cpu(real_length);
570
571 if ((expected_count < offset) ||
572 (expected_count > *len)) {
573 printf("%s:%d bad response size %d\n",
574 __FILE__, __LINE__,
575 expected_count);
576 return TPM_DRIVER_ERR;
577 }
578 }
579 }
580
581 /* Wait for the next portion */
Aaron Durbinc4220022013-07-24 16:02:14 -0500582 if (tis_wait_valid(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700583 printf("%s:%d failed to read response\n",
584 __FILE__, __LINE__);
585 return TPM_DRIVER_ERR;
586 }
587
588 if (offset == expected_count)
589 break; /* We got all we need */
590
Bill XIEa4bf0b72018-03-22 17:07:43 +0800591 /*
592 * Certain TPMs seem to need some delay between tis_wait_valid()
593 * and tis_has_valid_data(), or some race-condition-related
594 * issue will occur.
595 */
Julius Wernercd49cce2019-03-05 16:53:33 -0800596 if (CONFIG(TPM_RDRESP_NEED_DELAY))
Bill XIEa4bf0b72018-03-22 17:07:43 +0800597 udelay(10);
598
Aaron Durbinc4220022013-07-24 16:02:14 -0500599 } while (tis_has_valid_data(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700600
Aaron Durbinc4220022013-07-24 16:02:14 -0500601 /* * Make sure we indeed read all there was. */
602 if (tis_has_valid_data(locality)) {
603 printf("%s:%d wrong receive status: %x %d bytes left\n",
604 __FILE__, __LINE__, tpm_read_status(locality),
605 tpm_read_burst_count(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700606 return TPM_DRIVER_ERR;
607 }
608
609 /* Tell the TPM that we are done. */
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700610 if (tis_command_ready(locality) == TPM_TIMEOUT_ERR)
611 return TPM_DRIVER_ERR;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700612
613 *len = offset;
614 return 0;
615}
616
617/*
618 * tis_init()
619 *
620 * Initialize the TPM device. Returns 0 on success or TPM_DRIVER_ERR on
621 * failure (in case device probing did not succeed).
622 */
623int tis_init(void)
624{
625 if (tis_probe())
626 return TPM_DRIVER_ERR;
627 return 0;
628}
629
630/*
631 * tis_open()
632 *
633 * Requests access to locality 0 for the caller. After all commands have been
634 * completed the caller is supposed to call tis_close().
635 *
636 * Returns 0 on success, TPM_DRIVER_ERR on failure.
637 */
638int tis_open(void)
639{
640 u8 locality = 0; /* we use locality zero for everything */
641
642 if (tis_close())
643 return TPM_DRIVER_ERR;
644
645 /* now request access to locality */
Aaron Durbinc4220022013-07-24 16:02:14 -0500646 tis_request_access(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700647
648 /* did we get a lock? */
Aaron Durbinc4220022013-07-24 16:02:14 -0500649 if (tis_wait_received_access(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700650 printf("%s:%d - failed to lock locality %d\n",
651 __FILE__, __LINE__, locality);
652 return TPM_DRIVER_ERR;
653 }
654
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700655 /* Certain TPMs seem to need some delay here or they hang... */
656 udelay(10);
657
658 if (tis_command_ready(locality) == TPM_TIMEOUT_ERR)
659 return TPM_DRIVER_ERR;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700660
661 return 0;
662}
663
664/*
665 * tis_close()
666 *
Martin Roth56889792013-07-09 21:39:46 -0600667 * terminate the current session with the TPM by releasing the locked
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700668 * locality. Returns 0 on success of TPM_DRIVER_ERR on failure (in case lock
669 * removal did not succeed).
670 */
671int tis_close(void)
672{
673 u8 locality = 0;
Aaron Durbinc4220022013-07-24 16:02:14 -0500674 if (tis_has_access(locality)) {
675 tis_drop_access(locality);
676 if (tis_wait_dropped_access(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700677 printf("%s:%d - failed to release locality %d\n",
678 __FILE__, __LINE__, locality);
679 return TPM_DRIVER_ERR;
680 }
681 }
682 return 0;
683}
684
685/*
686 * tis_sendrecv()
687 *
688 * Send the requested data to the TPM and then try to get its response
689 *
690 * @sendbuf - buffer of the data to send
691 * @send_size size of the data to send
692 * @recvbuf - memory to save the response to
693 * @recv_len - pointer to the size of the response buffer
694 *
695 * Returns 0 on success (and places the number of response bytes at recv_len)
696 * or TPM_DRIVER_ERR on failure.
697 */
698int tis_sendrecv(const uint8_t *sendbuf, size_t send_size,
699 uint8_t *recvbuf, size_t *recv_len)
700{
701 if (tis_senddata(sendbuf, send_size)) {
702 printf("%s:%d failed sending data to TPM\n",
703 __FILE__, __LINE__);
704 return TPM_DRIVER_ERR;
705 }
706
707 return tis_readresponse(recvbuf, recv_len);
708}
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700709
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700710/*
711 * tis_setup_interrupt()
712 *
713 * Set up the interrupt vector and polarity for locality 0 and
714 * disable all interrupts so they are unused in firmware but can
715 * be enabled by the OS.
716 *
717 * The values used here must match what is passed in the TPM ACPI
718 * device if ACPI is used on the platform.
719 *
720 * @vector - TPM interrupt vector
721 * @polarity - TPM interrupt polarity
722 *
723 * Returns 0 on success, TPM_DRIVER_ERR on failure.
724 */
725static int tis_setup_interrupt(int vector, int polarity)
726{
727 u8 locality = 0;
728 int has_access = tis_has_access(locality);
729
730 /* Open connection and request access if not already granted */
731 if (!has_access && tis_open() < 0)
732 return TPM_DRIVER_ERR;
733
734 /* Set TPM interrupt vector */
735 tpm_write_int_vector(vector, locality);
736
Elyes HAOUAS18958382018-08-07 12:23:16 +0200737 /* Set TPM interrupt polarity and disable interrupts */
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700738 tpm_write_int_polarity(polarity, locality);
739
740 /* Close connection if it was opened */
741 if (!has_access && tis_close() < 0)
742 return TPM_DRIVER_ERR;
743
744 return 0;
745}
746
747static void lpc_tpm_read_resources(struct device *dev)
748{
749 /* Static 5K memory region specified in Kconfig */
750 mmio_resource(dev, 0, CONFIG_TPM_TIS_BASE_ADDRESS >> 10, 0x5000 >> 10);
751}
752
753static void lpc_tpm_set_resources(struct device *dev)
754{
755 tpm_config_t *config = (tpm_config_t *)dev->chip_info;
Kyösti Mälkkibaa16e92019-11-05 18:38:00 +0200756 DEVTREE_CONST struct resource *res;
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700757
758 for (res = dev->resource_list; res; res = res->next) {
759 if (!(res->flags & IORESOURCE_ASSIGNED))
760 continue;
761
762 if (res->flags & IORESOURCE_IRQ) {
763 /* Set interrupt vector */
764 tis_setup_interrupt((int)res->base,
765 config->irq_polarity);
766 } else {
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700767 continue;
768 }
769
Kyösti Mälkkibaa16e92019-11-05 18:38:00 +0200770#if !DEVTREE_EARLY
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700771 res->flags |= IORESOURCE_STORED;
772 report_resource_stored(dev, res, " <tpm>");
Kyösti Mälkkibaa16e92019-11-05 18:38:00 +0200773#endif
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700774 }
775}
776
Julius Wernercd49cce2019-03-05 16:53:33 -0800777#if CONFIG(HAVE_ACPI_TABLES)
Furquan Shaikh7536a392020-04-24 21:59:21 -0700778static void lpc_tpm_fill_ssdt(const struct device *dev)
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530779{
780 const char *path = acpi_device_path(dev->bus->dev);
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530781
Philipp Deppenwiese3a1fbea2016-12-14 01:06:55 +0100782 if (!path) {
Tobias Diedrich36537f12017-02-10 00:28:45 +0100783 path = "\\_SB_.PCI0.LPCB";
Philipp Deppenwiese3a1fbea2016-12-14 01:06:55 +0100784 printk(BIOS_DEBUG, "Using default TPM ACPI path: '%s'\n", path);
785 }
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530786
787 /* Device */
788 acpigen_write_scope(path);
789 acpigen_write_device(acpi_device_name(dev));
790
Michał Żygowski7b288012020-03-20 15:41:44 +0100791 if (CONFIG(TPM2)) {
792 acpigen_write_name_string("_HID", "MSFT0101");
793 acpigen_write_name_string("_CID", "MSFT0101");
794 } else {
795 acpigen_write_name("_HID");
796 acpigen_emit_eisaid("PNP0C31");
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530797
Michał Żygowski7b288012020-03-20 15:41:44 +0100798 acpigen_write_name("_CID");
799 acpigen_emit_eisaid("PNP0C31");
800 }
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530801
Patrick Rudolphc83bab62019-12-13 12:16:06 +0100802 acpi_device_write_uid(dev);
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530803
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530804 u32 did_vid = tpm_read_did_vid(0);
805 if (did_vid > 0 && did_vid < 0xffffffff)
806 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
807 else
808 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_OFF);
809
Kevin Cody-Littlec97b5af2018-05-09 14:14:59 -0400810 u16 port = dev->path.pnp.port;
811
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530812 /* Resources */
813 acpigen_write_name("_CRS");
814 acpigen_write_resourcetemplate_header();
815 acpigen_write_mem32fixed(1, CONFIG_TPM_TIS_BASE_ADDRESS, 0x5000);
Frans Hendriks6cc937e2018-10-29 14:30:58 +0100816 if (port)
817 acpigen_write_io16(port, port, 1, 2, 1);
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530818
819 if (CONFIG_TPM_PIRQ) {
820 /*
821 * PIRQ: Update interrupt vector with configured PIRQ
822 * Active-Low Level-Triggered Shared
823 */
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800824 struct acpi_irq tpm_irq_a = ACPI_IRQ_LEVEL_LOW(CONFIG_TPM_PIRQ);
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530825 acpi_device_write_interrupt(&tpm_irq_a);
826 } else if (tpm_read_int_vector(0) > 0) {
827 u8 int_vec = tpm_read_int_vector(0);
828 u8 int_pol = tpm_read_int_polarity(0);
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800829 struct acpi_irq tpm_irq = ACPI_IRQ_LEVEL_LOW(int_vec);
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530830
831 if (int_pol & 1)
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800832 tpm_irq.polarity = ACPI_IRQ_ACTIVE_LOW;
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530833 else
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800834 tpm_irq.polarity = ACPI_IRQ_ACTIVE_HIGH;
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530835
836 if (int_pol & 2)
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800837 tpm_irq.mode = ACPI_IRQ_EDGE_TRIGGERED;
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530838 else
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800839 tpm_irq.mode = ACPI_IRQ_LEVEL_TRIGGERED;
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530840
841 acpi_device_write_interrupt(&tpm_irq);
842 }
843
Patrick Rudolphd8d8be12020-09-21 09:48:53 +0200844
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530845 acpigen_write_resourcetemplate_footer();
846
Patrick Rudolphd8d8be12020-09-21 09:48:53 +0200847 if (!CONFIG(CHROMEOS))
848 tpm_ppi_acpi_fill_ssdt(dev);
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530849
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530850 acpigen_pop_len(); /* Device */
851 acpigen_pop_len(); /* Scope */
852
Kyösti Mälkkibaa16e92019-11-05 18:38:00 +0200853#if !DEVTREE_EARLY
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530854 printk(BIOS_INFO, "%s.%s: %s %s\n", path, acpi_device_name(dev),
855 dev->chip_ops->name, dev_path(dev));
Kyösti Mälkkibaa16e92019-11-05 18:38:00 +0200856#endif
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530857}
858
Aaron Durbinaa090cb2017-09-13 16:01:52 -0600859static const char *lpc_tpm_acpi_name(const struct device *dev)
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530860{
861 return "TPM";
862}
863#endif
864
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700865static struct device_operations lpc_tpm_ops = {
Elyes HAOUAS2aa3b162018-11-27 17:02:10 +0100866 .read_resources = lpc_tpm_read_resources,
867 .set_resources = lpc_tpm_set_resources,
Julius Wernercd49cce2019-03-05 16:53:33 -0800868#if CONFIG(HAVE_ACPI_TABLES)
Nico Huber68680dd2020-03-31 17:34:52 +0200869 .acpi_name = lpc_tpm_acpi_name,
870 .acpi_fill_ssdt = lpc_tpm_fill_ssdt,
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530871#endif
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700872};
873
874static struct pnp_info pnp_dev_info[] = {
875 { .flags = PNP_IRQ0 }
876};
877
878static void enable_dev(struct device *dev)
879{
Kyösti Mälkkid2b2a182021-04-29 15:33:07 +0300880 if (CONFIG(TPM))
Kyösti Mälkki9cc64932020-05-29 19:42:07 +0300881 pnp_enable_devices(dev, &lpc_tpm_ops,
882 ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700883}
884
885struct chip_operations drivers_pc80_tpm_ops = {
886 CHIP_NAME("LPC TPM")
887 .enable_dev = enable_dev
888};