blob: 98d31c0a82fdd78b567ffbb6bb30120863a2b726 [file] [log] [blame]
Angel Pons8a3453f2020-04-02 23:48:19 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Stefan Reinauer3008bbad2011-10-11 14:46:25 -07003
4/*
5 * The code in this file has been heavily based on the article "Writing a TPM
6 * Device Driver" published on http://ptgmedia.pearsoncmg.com and the
7 * submission by Stefan Berger on Qemu-devel mailing list.
8 *
9 * One principal difference is that in the simplest config the other than 0
10 * TPM localities do not get mapped by some devices (for instance, by
11 * Infineon slb9635), so this driver provides access to locality 0 only.
12 */
13
Elyes HAOUAS361a9352019-12-18 21:26:33 +010014#include <commonlib/helpers.h>
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070015#include <string.h>
16#include <delay.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020017#include <device/mmio.h>
Naresh G Solanki80ff0382016-11-15 11:01:33 +053018#include <arch/acpi.h>
19#include <arch/acpigen.h>
20#include <arch/acpi_device.h>
21#include <device/device.h>
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070022#include <console/console.h>
Philipp Deppenwiesed88fb362017-10-18 20:26:18 +020023#include <security/tpm/tis.h>
Duncan Lauriedd281ed2014-10-30 15:20:19 -070024#include <device/pnp.h>
25#include "chip.h"
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070026
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070027#define PREFIX "lpc_tpm: "
Naresh G Solanki80ff0382016-11-15 11:01:33 +053028/* TCG Physical Presence Interface */
29#define TPM_PPI_UUID "3dddfaa6-361b-4eb4-a424-8d10089d1653"
30/* TCG Memory Clear Interface */
31#define TPM_MCI_UUID "376054ed-cc13-4675-901c-4756d7f2d45d"
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070032/* coreboot wrapper for TPM driver (start) */
33#define TPM_DEBUG(fmt, args...) \
Julius Wernercd49cce2019-03-05 16:53:33 -080034 if (CONFIG(DEBUG_TPM)) { \
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070035 printk(BIOS_DEBUG, PREFIX); \
Elyes HAOUASa342f392018-10-17 10:56:26 +020036 printk(BIOS_DEBUG, fmt, ##args); \
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070037 }
Aaron Durbinc4220022013-07-24 16:02:14 -050038#define TPM_DEBUG_IO_READ(reg_, val_) \
39 TPM_DEBUG("Read reg 0x%x returns 0x%x\n", (reg_), (val_))
40#define TPM_DEBUG_IO_WRITE(reg_, val_) \
41 TPM_DEBUG("Write reg 0x%x with 0x%x\n", (reg_), (val_))
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070042#define printf(x...) printk(BIOS_ERR, x)
43
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070044/* coreboot wrapper for TPM driver (end) */
45
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070046/* the macro accepts the locality value, but only locality 0 is operational */
47#define TIS_REG(LOCALITY, REG) \
Martin Rothb9810a42017-07-23 20:00:04 -060048 (void *)(CONFIG_TPM_TIS_BASE_ADDRESS + (LOCALITY << 12) + REG)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070049
50/* hardware registers' offsets */
51#define TIS_REG_ACCESS 0x0
52#define TIS_REG_INT_ENABLE 0x8
53#define TIS_REG_INT_VECTOR 0xc
54#define TIS_REG_INT_STATUS 0x10
55#define TIS_REG_INTF_CAPABILITY 0x14
56#define TIS_REG_STS 0x18
Aaron Durbinc4220022013-07-24 16:02:14 -050057#define TIS_REG_BURST_COUNT 0x19
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070058#define TIS_REG_DATA_FIFO 0x24
59#define TIS_REG_DID_VID 0xf00
60#define TIS_REG_RID 0xf04
61
62/* Some registers' bit field definitions */
63#define TIS_STS_VALID (1 << 7) /* 0x80 */
64#define TIS_STS_COMMAND_READY (1 << 6) /* 0x40 */
65#define TIS_STS_TPM_GO (1 << 5) /* 0x20 */
66#define TIS_STS_DATA_AVAILABLE (1 << 4) /* 0x10 */
67#define TIS_STS_EXPECT (1 << 3) /* 0x08 */
68#define TIS_STS_RESPONSE_RETRY (1 << 1) /* 0x02 */
69
70#define TIS_ACCESS_TPM_REG_VALID_STS (1 << 7) /* 0x80 */
71#define TIS_ACCESS_ACTIVE_LOCALITY (1 << 5) /* 0x20 */
72#define TIS_ACCESS_BEEN_SEIZED (1 << 4) /* 0x10 */
73#define TIS_ACCESS_SEIZE (1 << 3) /* 0x08 */
74#define TIS_ACCESS_PENDING_REQUEST (1 << 2) /* 0x04 */
75#define TIS_ACCESS_REQUEST_USE (1 << 1) /* 0x02 */
76#define TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0) /* 0x01 */
77
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070078/*
79 * Error value returned if a tpm register does not enter the expected state
80 * after continuous polling. No actual TPM register reading ever returns ~0,
81 * so this value is a safe error indication to be mixed with possible status
82 * register values.
83 */
84#define TPM_TIMEOUT_ERR (~0)
85
86/* Error value returned on various TPM driver errors */
87#define TPM_DRIVER_ERR (~0)
88
89 /* 1 second is plenty for anything TPM does.*/
90#define MAX_DELAY_US (1000 * 1000)
91
Stefan Reinauer3008bbad2011-10-11 14:46:25 -070092/*
93 * Structures defined below allow creating descriptions of TPM vendor/device
94 * ID information for run time discovery. The only device the system knows
95 * about at this time is Infineon slb9635
96 */
97struct device_name {
98 u16 dev_id;
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +020099 const char *const dev_name;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700100};
101
102struct vendor_name {
103 u16 vendor_id;
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +0200104 const char *vendor_name;
105 const struct device_name *dev_names;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700106};
107
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700108static const struct device_name atmel_devices[] = {
109 {0x3204, "AT97SC3204"},
110 {0xffff}
111};
112
Stefan Reinauerc668af72011-10-27 21:28:25 +0000113static const struct device_name infineon_devices[] = {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700114 {0x000b, "SLB9635 TT 1.2"},
Julius Wernercd49cce2019-03-05 16:53:33 -0800115#if CONFIG(TPM2)
Kamil Wcislobf5ccfd2017-10-12 13:12:11 +0200116 {0x001a, "SLB9665 TT 2.0"},
Subrata Banik5b8c4a72016-11-11 09:28:45 +0530117 {0x001b, "SLB9670 TT 2.0"},
118#else
Kamil Wcislobf5ccfd2017-10-12 13:12:11 +0200119 {0x001a, "SLB9660 TT 1.2"},
Wenkai Du641529b2015-05-29 10:54:27 -0700120 {0x001b, "SLB9670 TT 1.2"},
Subrata Banik5b8c4a72016-11-11 09:28:45 +0530121#endif
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700122 {0xffff}
123};
124
125static const struct device_name nuvoton_devices[] = {
126 {0x00fe, "NPCT420AA V2"},
127 {0xffff}
128};
129
130static const struct device_name stmicro_devices[] = {
131 {0x0000, "ST33ZP24" },
132 {0xffff}
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700133};
134
Tsung Ho Wu804a0432019-06-07 15:03:49 -0700135static const struct device_name swtpm_devices[] = {
136#if CONFIG(TPM2)
137 {0x0001, "SwTPM 2.0" },
138#endif
139 {0xffff}
140};
141
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700142static const struct vendor_name vendor_names[] = {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700143 {0x1114, "Atmel", atmel_devices},
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700144 {0x15d1, "Infineon", infineon_devices},
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700145 {0x1050, "Nuvoton", nuvoton_devices},
Tsung Ho Wu804a0432019-06-07 15:03:49 -0700146 {0x1014, "TPM Emulator", swtpm_devices},
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700147 {0x104a, "ST Microelectronics", stmicro_devices},
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700148};
149
150/*
151 * Cached vendor/device ID pair to indicate that the device has been already
152 * discovered
153 */
Arthur Heymans0ca944b2019-11-20 19:51:06 +0100154static u32 vendor_dev_id;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700155
Aaron Durbinc4220022013-07-24 16:02:14 -0500156static inline u8 tpm_read_status(int locality)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700157{
Julius Werner2f37bd62015-02-19 14:51:15 -0800158 u8 value = read8(TIS_REG(locality, TIS_REG_STS));
Aaron Durbinc4220022013-07-24 16:02:14 -0500159 TPM_DEBUG_IO_READ(TIS_REG_STS, value);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700160 return value;
161}
162
Aaron Durbinc4220022013-07-24 16:02:14 -0500163static inline void tpm_write_status(u8 sts, int locality)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700164{
Aaron Durbinc4220022013-07-24 16:02:14 -0500165 TPM_DEBUG_IO_WRITE(TIS_REG_STS, sts);
Julius Werner2f37bd62015-02-19 14:51:15 -0800166 write8(TIS_REG(locality, TIS_REG_STS), sts);
Aaron Durbinc4220022013-07-24 16:02:14 -0500167}
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700168
Aaron Durbinc4220022013-07-24 16:02:14 -0500169static inline u8 tpm_read_data(int locality)
170{
Julius Werner2f37bd62015-02-19 14:51:15 -0800171 u8 value = read8(TIS_REG(locality, TIS_REG_DATA_FIFO));
Aaron Durbinc4220022013-07-24 16:02:14 -0500172 TPM_DEBUG_IO_READ(TIS_REG_DATA_FIFO, value);
173 return value;
174}
175
176static inline void tpm_write_data(u8 data, int locality)
177{
178 TPM_DEBUG_IO_WRITE(TIS_REG_STS, data);
Julius Werner2f37bd62015-02-19 14:51:15 -0800179 write8(TIS_REG(locality, TIS_REG_DATA_FIFO), data);
Aaron Durbinc4220022013-07-24 16:02:14 -0500180}
181
182static inline u16 tpm_read_burst_count(int locality)
183{
184 u16 count;
Julius Werner2f37bd62015-02-19 14:51:15 -0800185 count = read8(TIS_REG(locality, TIS_REG_BURST_COUNT));
186 count |= read8(TIS_REG(locality, TIS_REG_BURST_COUNT + 1)) << 8;
Aaron Durbinc4220022013-07-24 16:02:14 -0500187 TPM_DEBUG_IO_READ(TIS_REG_BURST_COUNT, count);
188 return count;
189}
190
191static inline u8 tpm_read_access(int locality)
192{
Julius Werner2f37bd62015-02-19 14:51:15 -0800193 u8 value = read8(TIS_REG(locality, TIS_REG_ACCESS));
Aaron Durbinc4220022013-07-24 16:02:14 -0500194 TPM_DEBUG_IO_READ(TIS_REG_ACCESS, value);
195 return value;
196}
197
198static inline void tpm_write_access(u8 data, int locality)
199{
200 TPM_DEBUG_IO_WRITE(TIS_REG_ACCESS, data);
Julius Werner2f37bd62015-02-19 14:51:15 -0800201 write8(TIS_REG(locality, TIS_REG_ACCESS), data);
Aaron Durbinc4220022013-07-24 16:02:14 -0500202}
203
204static inline u32 tpm_read_did_vid(int locality)
205{
Julius Werner2f37bd62015-02-19 14:51:15 -0800206 u32 value = read32(TIS_REG(locality, TIS_REG_DID_VID));
Aaron Durbinc4220022013-07-24 16:02:14 -0500207 TPM_DEBUG_IO_READ(TIS_REG_DID_VID, value);
208 return value;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700209}
210
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700211static inline void tpm_write_int_vector(int vector, int locality)
212{
213 TPM_DEBUG_IO_WRITE(TIS_REG_INT_VECTOR, vector);
Julius Werner2f37bd62015-02-19 14:51:15 -0800214 write8(TIS_REG(locality, TIS_REG_INT_VECTOR), vector & 0xf);
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700215}
216
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530217static inline u8 tpm_read_int_vector(int locality)
218{
219 u8 value = read8(TIS_REG(locality, TIS_REG_INT_VECTOR));
220 TPM_DEBUG_IO_READ(TIS_REG_INT_VECTOR, value);
221 return value;
222}
223
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700224static inline void tpm_write_int_polarity(int polarity, int locality)
225{
226 /* Set polarity and leave all other bits at 0 */
227 u32 value = (polarity & 0x3) << 3;
228 TPM_DEBUG_IO_WRITE(TIS_REG_INT_ENABLE, value);
Julius Werner2f37bd62015-02-19 14:51:15 -0800229 write32(TIS_REG(locality, TIS_REG_INT_ENABLE), value);
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700230}
231
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530232static inline u32 tpm_read_int_polarity(int locality)
233{
234 /* Get polarity and leave all other bits */
235 u32 value = read8(TIS_REG(locality, TIS_REG_INT_ENABLE));
236 value = (value >> 3) & 0x3;
237 TPM_DEBUG_IO_READ(TIS_REG_INT_ENABLE, value);
238 return value;
239}
240
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700241/*
Aaron Durbinc4220022013-07-24 16:02:14 -0500242 * tis_wait_sts()
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700243 *
Aaron Durbinc4220022013-07-24 16:02:14 -0500244 * Wait for at least a second for a status to change its state to match the
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700245 * expected state. Normally the transition happens within microseconds.
246 *
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700247 * @locality - locality
248 * @mask - bitmask for the bitfield(s) to watch
249 * @expected - value the field(s) are supposed to be set to
250 *
Aaron Durbinc4220022013-07-24 16:02:14 -0500251 * Returns 0 on success or TPM_TIMEOUT_ERR on timeout.
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700252 */
Aaron Durbinc4220022013-07-24 16:02:14 -0500253static int tis_wait_sts(int locality, u8 mask, u8 expected)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700254{
255 u32 time_us = MAX_DELAY_US;
256 while (time_us > 0) {
Aaron Durbinc4220022013-07-24 16:02:14 -0500257 u8 value = tpm_read_status(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700258 if ((value & mask) == expected)
Aaron Durbinc4220022013-07-24 16:02:14 -0500259 return 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700260 udelay(1); /* 1 us */
261 time_us--;
262 }
263 return TPM_TIMEOUT_ERR;
264}
265
Aaron Durbinc4220022013-07-24 16:02:14 -0500266static inline int tis_wait_ready(int locality)
267{
268 return tis_wait_sts(locality, TIS_STS_COMMAND_READY,
269 TIS_STS_COMMAND_READY);
270}
271
272static inline int tis_wait_valid(int locality)
273{
274 return tis_wait_sts(locality, TIS_STS_VALID, TIS_STS_VALID);
275}
276
277static inline int tis_wait_valid_data(int locality)
278{
279 const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID;
280 return tis_wait_sts(locality, has_data, has_data);
281}
282
283static inline int tis_has_valid_data(int locality)
284{
285 const u8 has_data = TIS_STS_DATA_AVAILABLE | TIS_STS_VALID;
286 return (tpm_read_status(locality) & has_data) == has_data;
287}
288
289static inline int tis_expect_data(int locality)
290{
291 return !!(tpm_read_status(locality) & TIS_STS_EXPECT);
292}
293
294/*
295 * tis_wait_access()
296 *
297 * Wait for at least a second for a access to change its state to match the
298 * expected state. Normally the transition happens within microseconds.
299 *
300 * @locality - locality
301 * @mask - bitmask for the bitfield(s) to watch
302 * @expected - value the field(s) are supposed to be set to
303 *
304 * Returns 0 on success or TPM_TIMEOUT_ERR on timeout.
305 */
306static int tis_wait_access(int locality, u8 mask, u8 expected)
307{
308 u32 time_us = MAX_DELAY_US;
309 while (time_us > 0) {
310 u8 value = tpm_read_access(locality);
311 if ((value & mask) == expected)
312 return 0;
313 udelay(1); /* 1 us */
314 time_us--;
315 }
316 return TPM_TIMEOUT_ERR;
317}
318
319static inline int tis_wait_dropped_access(int locality)
320{
321 return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY, 0);
322}
323
324static inline int tis_wait_received_access(int locality)
325{
326 return tis_wait_access(locality, TIS_ACCESS_ACTIVE_LOCALITY,
327 TIS_ACCESS_ACTIVE_LOCALITY);
328}
329
330static inline int tis_has_access(int locality)
331{
332 return !!(tpm_read_access(locality) & TIS_ACCESS_ACTIVE_LOCALITY);
333}
334
335static inline void tis_request_access(int locality)
336{
337 tpm_write_access(TIS_ACCESS_REQUEST_USE, locality);
338}
339
340static inline void tis_drop_access(int locality)
341{
342 tpm_write_access(TIS_ACCESS_ACTIVE_LOCALITY, locality);
343}
344
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700345/*
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700346 * PC Client Specific TPM Interface Specification section 11.2.12:
347 *
348 * Software must be prepared to send two writes of a "1" to command ready
349 * field: the first to indicate successful read of all the data, thus
350 * clearing the data from the ReadFIFO and freeing the TPM's resources,
351 * and the second to indicate to the TPM it is about to send a new command.
352 *
353 * In practice not all TPMs behave the same so it is necessary to be
354 * flexible when trying to set command ready.
355 *
356 * Returns 0 on success if the TPM is ready for transactions.
357 * Returns TPM_TIMEOUT_ERR if the command ready bit does not get set.
358 */
359static int tis_command_ready(u8 locality)
360{
361 u32 status;
362
363 /* 1st attempt to set command ready */
Aaron Durbinc4220022013-07-24 16:02:14 -0500364 tpm_write_status(TIS_STS_COMMAND_READY, locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700365
366 /* Wait for response */
Aaron Durbinc4220022013-07-24 16:02:14 -0500367 status = tpm_read_status(locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700368
369 /* Check if command ready is set yet */
370 if (status & TIS_STS_COMMAND_READY)
371 return 0;
372
373 /* 2nd attempt to set command ready */
Aaron Durbinc4220022013-07-24 16:02:14 -0500374 tpm_write_status(TIS_STS_COMMAND_READY, locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700375
Aaron Durbinc4220022013-07-24 16:02:14 -0500376 return tis_wait_ready(locality);
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700377}
378
379/*
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700380 * Probe the TPM device and try determining its manufacturer/device name.
381 *
382 * Returns 0 on success (the device is found or was found during an earlier
383 * invocation) or TPM_DRIVER_ERR if the device is not found.
384 */
385static u32 tis_probe(void)
386{
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700387 const char *device_name = "unknown";
388 const char *vendor_name = device_name;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700389 const struct device_name *dev;
390 u32 didvid;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700391 u16 vid, did;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700392 int i;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700393
Arthur Heymans0ca944b2019-11-20 19:51:06 +0100394 if (vendor_dev_id)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700395 return 0; /* Already probed. */
396
Aaron Durbinc4220022013-07-24 16:02:14 -0500397 didvid = tpm_read_did_vid(0);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700398 if (!didvid || (didvid == 0xffffffff)) {
399 printf("%s: No TPM device found\n", __FUNCTION__);
400 return TPM_DRIVER_ERR;
401 }
402
Arthur Heymans0ca944b2019-11-20 19:51:06 +0100403 vendor_dev_id = didvid;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700404
405 vid = didvid & 0xffff;
406 did = (didvid >> 16) & 0xffff;
407 for (i = 0; i < ARRAY_SIZE(vendor_names); i++) {
408 int j = 0;
409 u16 known_did;
410 if (vid == vendor_names[i].vendor_id) {
411 vendor_name = vendor_names[i].vendor_name;
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700412 } else {
413 continue;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700414 }
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700415 dev = &vendor_names[i].dev_names[j];
416 while ((known_did = dev->dev_id) != 0xffff) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700417 if (known_did == did) {
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700418 device_name = dev->dev_name;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700419 break;
420 }
421 j++;
Subrata41b08d92015-05-14 14:38:07 +0530422 dev = &vendor_names[i].dev_names[j];
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700423 }
424 break;
425 }
426 /* this will have to be converted into debug printout */
Duncan Laurie17ba9442015-09-03 16:00:49 -0700427 printk(BIOS_INFO, "Found TPM %s by %s\n", device_name, vendor_name);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700428 return 0;
429}
430
431/*
432 * tis_senddata()
433 *
434 * send the passed in data to the TPM device.
435 *
436 * @data - address of the data to send, byte by byte
437 * @len - length of the data to send
438 *
439 * Returns 0 on success, TPM_DRIVER_ERR on error (in case the device does
440 * not accept the entire command).
441 */
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +0200442static u32 tis_senddata(const u8 *const data, u32 len)
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700443{
444 u32 offset = 0;
445 u16 burst = 0;
446 u32 max_cycles = 0;
447 u8 locality = 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700448
Aaron Durbinc4220022013-07-24 16:02:14 -0500449 if (tis_wait_ready(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700450 printf("%s:%d - failed to get 'command_ready' status\n",
451 __FILE__, __LINE__);
452 return TPM_DRIVER_ERR;
453 }
Aaron Durbinc4220022013-07-24 16:02:14 -0500454 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700455
456 while (1) {
Martin Roth38ddbfb2019-10-23 21:41:00 -0600457 unsigned int count;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700458
459 /* Wait till the device is ready to accept more data. */
460 while (!burst) {
461 if (max_cycles++ == MAX_DELAY_US) {
462 printf("%s:%d failed to feed %d bytes of %d\n",
463 __FILE__, __LINE__, len - offset, len);
464 return TPM_DRIVER_ERR;
465 }
466 udelay(1);
Aaron Durbinc4220022013-07-24 16:02:14 -0500467 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700468 }
469
470 max_cycles = 0;
471
472 /*
473 * Calculate number of bytes the TPM is ready to accept in one
474 * shot.
475 *
476 * We want to send the last byte outside of the loop (hence
477 * the -1 below) to make sure that the 'expected' status bit
478 * changes to zero exactly after the last byte is fed into the
479 * FIFO.
480 */
Elyes HAOUAS361a9352019-12-18 21:26:33 +0100481 count = MIN(burst, len - offset - 1);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700482 while (count--)
Aaron Durbinc4220022013-07-24 16:02:14 -0500483 tpm_write_data(data[offset++], locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700484
Aaron Durbinc4220022013-07-24 16:02:14 -0500485 if (tis_wait_valid(locality) || !tis_expect_data(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700486 printf("%s:%d TPM command feed overflow\n",
487 __FILE__, __LINE__);
488 return TPM_DRIVER_ERR;
489 }
490
Aaron Durbinc4220022013-07-24 16:02:14 -0500491 burst = tpm_read_burst_count(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700492 if ((offset == (len - 1)) && burst)
493 /*
494 * We need to be able to send the last byte to the
495 * device, so burst size must be nonzero before we
496 * break out.
497 */
498 break;
499 }
500
501 /* Send the last byte. */
Aaron Durbinc4220022013-07-24 16:02:14 -0500502 tpm_write_data(data[offset++], locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700503
504 /*
505 * Verify that TPM does not expect any more data as part of this
506 * command.
507 */
Aaron Durbinc4220022013-07-24 16:02:14 -0500508 if (tis_wait_valid(locality) || tis_expect_data(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700509 printf("%s:%d unexpected TPM status 0x%x\n",
Aaron Durbinc4220022013-07-24 16:02:14 -0500510 __FILE__, __LINE__, tpm_read_status(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700511 return TPM_DRIVER_ERR;
512 }
513
514 /* OK, sitting pretty, let's start the command execution. */
Aaron Durbinc4220022013-07-24 16:02:14 -0500515 tpm_write_status(TIS_STS_TPM_GO, locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700516
517 return 0;
518}
519
520/*
521 * tis_readresponse()
522 *
523 * read the TPM device response after a command was issued.
524 *
525 * @buffer - address where to read the response, byte by byte.
526 * @len - pointer to the size of buffer
527 *
528 * On success stores the number of received bytes to len and returns 0. On
529 * errors (misformatted TPM data or synchronization problems) returns
530 * TPM_DRIVER_ERR.
531 */
532static u32 tis_readresponse(u8 *buffer, size_t *len)
533{
534 u16 burst_count;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700535 u32 offset = 0;
536 u8 locality = 0;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700537 u32 expected_count = *len;
538 int max_cycles = 0;
539
540 /* Wait for the TPM to process the command */
Aaron Durbinc4220022013-07-24 16:02:14 -0500541 if (tis_wait_valid_data(locality)) {
542 printf("%s:%d failed processing command\n", __FILE__, __LINE__);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700543 return TPM_DRIVER_ERR;
544 }
545
546 do {
Aaron Durbinc4220022013-07-24 16:02:14 -0500547 while ((burst_count = tpm_read_burst_count(locality)) == 0) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700548 if (max_cycles++ == MAX_DELAY_US) {
549 printf("%s:%d TPM stuck on read\n",
550 __FILE__, __LINE__);
551 return TPM_DRIVER_ERR;
552 }
553 udelay(1);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700554 }
555
556 max_cycles = 0;
557
558 while (burst_count-- && (offset < expected_count)) {
Aaron Durbinc4220022013-07-24 16:02:14 -0500559 buffer[offset++] = tpm_read_data(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700560 if (offset == 6) {
561 /*
562 * We got the first six bytes of the reply,
563 * let's figure out how many bytes to expect
564 * total - it is stored as a 4 byte number in
565 * network order, starting with offset 2 into
566 * the body of the reply.
567 */
568 u32 real_length;
569 memcpy(&real_length,
570 buffer + 2,
571 sizeof(real_length));
572 expected_count = be32_to_cpu(real_length);
573
574 if ((expected_count < offset) ||
575 (expected_count > *len)) {
576 printf("%s:%d bad response size %d\n",
577 __FILE__, __LINE__,
578 expected_count);
579 return TPM_DRIVER_ERR;
580 }
581 }
582 }
583
584 /* Wait for the next portion */
Aaron Durbinc4220022013-07-24 16:02:14 -0500585 if (tis_wait_valid(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700586 printf("%s:%d failed to read response\n",
587 __FILE__, __LINE__);
588 return TPM_DRIVER_ERR;
589 }
590
591 if (offset == expected_count)
592 break; /* We got all we need */
593
Bill XIEa4bf0b72018-03-22 17:07:43 +0800594 /*
595 * Certain TPMs seem to need some delay between tis_wait_valid()
596 * and tis_has_valid_data(), or some race-condition-related
597 * issue will occur.
598 */
Julius Wernercd49cce2019-03-05 16:53:33 -0800599 if (CONFIG(TPM_RDRESP_NEED_DELAY))
Bill XIEa4bf0b72018-03-22 17:07:43 +0800600 udelay(10);
601
Aaron Durbinc4220022013-07-24 16:02:14 -0500602 } while (tis_has_valid_data(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700603
Aaron Durbinc4220022013-07-24 16:02:14 -0500604 /* * Make sure we indeed read all there was. */
605 if (tis_has_valid_data(locality)) {
606 printf("%s:%d wrong receive status: %x %d bytes left\n",
607 __FILE__, __LINE__, tpm_read_status(locality),
608 tpm_read_burst_count(locality));
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700609 return TPM_DRIVER_ERR;
610 }
611
612 /* Tell the TPM that we are done. */
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700613 if (tis_command_ready(locality) == TPM_TIMEOUT_ERR)
614 return TPM_DRIVER_ERR;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700615
616 *len = offset;
617 return 0;
618}
619
620/*
621 * tis_init()
622 *
623 * Initialize the TPM device. Returns 0 on success or TPM_DRIVER_ERR on
624 * failure (in case device probing did not succeed).
625 */
626int tis_init(void)
627{
628 if (tis_probe())
629 return TPM_DRIVER_ERR;
630 return 0;
631}
632
633/*
634 * tis_open()
635 *
636 * Requests access to locality 0 for the caller. After all commands have been
637 * completed the caller is supposed to call tis_close().
638 *
639 * Returns 0 on success, TPM_DRIVER_ERR on failure.
640 */
641int tis_open(void)
642{
643 u8 locality = 0; /* we use locality zero for everything */
644
645 if (tis_close())
646 return TPM_DRIVER_ERR;
647
648 /* now request access to locality */
Aaron Durbinc4220022013-07-24 16:02:14 -0500649 tis_request_access(locality);
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700650
651 /* did we get a lock? */
Aaron Durbinc4220022013-07-24 16:02:14 -0500652 if (tis_wait_received_access(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700653 printf("%s:%d - failed to lock locality %d\n",
654 __FILE__, __LINE__, locality);
655 return TPM_DRIVER_ERR;
656 }
657
Stefan Reinauerc908fc72012-04-30 16:33:44 -0700658 /* Certain TPMs seem to need some delay here or they hang... */
659 udelay(10);
660
661 if (tis_command_ready(locality) == TPM_TIMEOUT_ERR)
662 return TPM_DRIVER_ERR;
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700663
664 return 0;
665}
666
667/*
668 * tis_close()
669 *
Martin Roth56889792013-07-09 21:39:46 -0600670 * terminate the current session with the TPM by releasing the locked
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700671 * locality. Returns 0 on success of TPM_DRIVER_ERR on failure (in case lock
672 * removal did not succeed).
673 */
674int tis_close(void)
675{
676 u8 locality = 0;
Aaron Durbinc4220022013-07-24 16:02:14 -0500677 if (tis_has_access(locality)) {
678 tis_drop_access(locality);
679 if (tis_wait_dropped_access(locality)) {
Stefan Reinauer3008bbad2011-10-11 14:46:25 -0700680 printf("%s:%d - failed to release locality %d\n",
681 __FILE__, __LINE__, locality);
682 return TPM_DRIVER_ERR;
683 }
684 }
685 return 0;
686}
687
688/*
689 * tis_sendrecv()
690 *
691 * Send the requested data to the TPM and then try to get its response
692 *
693 * @sendbuf - buffer of the data to send
694 * @send_size size of the data to send
695 * @recvbuf - memory to save the response to
696 * @recv_len - pointer to the size of the response buffer
697 *
698 * Returns 0 on success (and places the number of response bytes at recv_len)
699 * or TPM_DRIVER_ERR on failure.
700 */
701int tis_sendrecv(const uint8_t *sendbuf, size_t send_size,
702 uint8_t *recvbuf, size_t *recv_len)
703{
704 if (tis_senddata(sendbuf, send_size)) {
705 printf("%s:%d failed sending data to TPM\n",
706 __FILE__, __LINE__);
707 return TPM_DRIVER_ERR;
708 }
709
710 return tis_readresponse(recvbuf, recv_len);
711}
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700712
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700713/*
714 * tis_setup_interrupt()
715 *
716 * Set up the interrupt vector and polarity for locality 0 and
717 * disable all interrupts so they are unused in firmware but can
718 * be enabled by the OS.
719 *
720 * The values used here must match what is passed in the TPM ACPI
721 * device if ACPI is used on the platform.
722 *
723 * @vector - TPM interrupt vector
724 * @polarity - TPM interrupt polarity
725 *
726 * Returns 0 on success, TPM_DRIVER_ERR on failure.
727 */
728static int tis_setup_interrupt(int vector, int polarity)
729{
730 u8 locality = 0;
731 int has_access = tis_has_access(locality);
732
733 /* Open connection and request access if not already granted */
734 if (!has_access && tis_open() < 0)
735 return TPM_DRIVER_ERR;
736
737 /* Set TPM interrupt vector */
738 tpm_write_int_vector(vector, locality);
739
Elyes HAOUAS18958382018-08-07 12:23:16 +0200740 /* Set TPM interrupt polarity and disable interrupts */
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700741 tpm_write_int_polarity(polarity, locality);
742
743 /* Close connection if it was opened */
744 if (!has_access && tis_close() < 0)
745 return TPM_DRIVER_ERR;
746
747 return 0;
748}
749
750static void lpc_tpm_read_resources(struct device *dev)
751{
752 /* Static 5K memory region specified in Kconfig */
753 mmio_resource(dev, 0, CONFIG_TPM_TIS_BASE_ADDRESS >> 10, 0x5000 >> 10);
754}
755
756static void lpc_tpm_set_resources(struct device *dev)
757{
758 tpm_config_t *config = (tpm_config_t *)dev->chip_info;
Kyösti Mälkkibaa16e92019-11-05 18:38:00 +0200759 DEVTREE_CONST struct resource *res;
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700760
761 for (res = dev->resource_list; res; res = res->next) {
762 if (!(res->flags & IORESOURCE_ASSIGNED))
763 continue;
764
765 if (res->flags & IORESOURCE_IRQ) {
766 /* Set interrupt vector */
767 tis_setup_interrupt((int)res->base,
768 config->irq_polarity);
769 } else {
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700770 continue;
771 }
772
Kyösti Mälkkibaa16e92019-11-05 18:38:00 +0200773#if !DEVTREE_EARLY
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700774 res->flags |= IORESOURCE_STORED;
775 report_resource_stored(dev, res, " <tpm>");
Kyösti Mälkkibaa16e92019-11-05 18:38:00 +0200776#endif
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700777 }
778}
779
Julius Wernercd49cce2019-03-05 16:53:33 -0800780#if CONFIG(HAVE_ACPI_TABLES)
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530781
782static void tpm_ppi_func0_cb(void *arg)
783{
784 /* Functions 1-8. */
785 u8 buf[] = {0xff, 0x01};
786 acpigen_write_return_byte_buffer(buf, 2);
787}
788
789static void tpm_ppi_func1_cb(void *arg)
790{
Julius Wernercd49cce2019-03-05 16:53:33 -0800791 if (CONFIG(TPM2))
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530792 /* Interface version: 2.0 */
793 acpigen_write_return_string("2.0");
794 else
795 /* Interface version: 1.2 */
796 acpigen_write_return_string("1.2");
797}
798
799static void tpm_ppi_func2_cb(void *arg)
800{
801 /* Submit operations: drop on the floor and return success. */
802 acpigen_write_return_byte(0);
803}
804
805static void tpm_ppi_func3_cb(void *arg)
806{
807 /* Pending operation: none. */
808 acpigen_emit_byte(RETURN_OP);
809 acpigen_write_package(2);
810 acpigen_write_byte(0);
811 acpigen_write_byte(0);
812 acpigen_pop_len();
813}
814static void tpm_ppi_func4_cb(void *arg)
815{
816 /* Pre-OS transition method: reboot. */
817 acpigen_write_return_byte(2);
818}
819static void tpm_ppi_func5_cb(void *arg)
820{
821 /* Operation response: no operation executed. */
822 acpigen_emit_byte(RETURN_OP);
823 acpigen_write_package(3);
824 acpigen_write_byte(0);
825 acpigen_write_byte(0);
826 acpigen_write_byte(0);
827 acpigen_pop_len();
828}
829static void tpm_ppi_func6_cb(void *arg)
830{
831 /*
832 * Set preferred user language: deprecated and must return 3 aka
833 * "not implemented".
834 */
835 acpigen_write_return_byte(3);
836}
837static void tpm_ppi_func7_cb(void *arg)
838{
839 /* Submit operations: deny. */
840 acpigen_write_return_byte(3);
841}
842static void tpm_ppi_func8_cb(void *arg)
843{
844 /* All actions are forbidden. */
845 acpigen_write_return_byte(1);
846}
847static void (*tpm_ppi_callbacks[])(void *) = {
848 tpm_ppi_func0_cb,
849 tpm_ppi_func1_cb,
850 tpm_ppi_func2_cb,
851 tpm_ppi_func3_cb,
852 tpm_ppi_func4_cb,
853 tpm_ppi_func5_cb,
854 tpm_ppi_func6_cb,
855 tpm_ppi_func7_cb,
856 tpm_ppi_func8_cb,
857};
858
859static void tpm_mci_func0_cb(void *arg)
860{
861 /* Function 1. */
862 acpigen_write_return_singleton_buffer(0x3);
863}
864static void tpm_mci_func1_cb(void *arg)
865{
866 /* Just return success. */
867 acpigen_write_return_byte(0);
868}
869
870static void (*tpm_mci_callbacks[])(void *) = {
871 tpm_mci_func0_cb,
872 tpm_mci_func1_cb,
873};
874
875static void lpc_tpm_fill_ssdt(struct device *dev)
876{
877 const char *path = acpi_device_path(dev->bus->dev);
878 u32 arg;
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530879
Philipp Deppenwiese3a1fbea2016-12-14 01:06:55 +0100880 if (!path) {
Tobias Diedrich36537f12017-02-10 00:28:45 +0100881 path = "\\_SB_.PCI0.LPCB";
Philipp Deppenwiese3a1fbea2016-12-14 01:06:55 +0100882 printk(BIOS_DEBUG, "Using default TPM ACPI path: '%s'\n", path);
883 }
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530884
885 /* Device */
886 acpigen_write_scope(path);
887 acpigen_write_device(acpi_device_name(dev));
888
889 acpigen_write_name("_HID");
890 acpigen_emit_eisaid("PNP0C31");
891
892 acpigen_write_name("_CID");
893 acpigen_emit_eisaid("PNP0C31");
894
Patrick Rudolphc83bab62019-12-13 12:16:06 +0100895 acpi_device_write_uid(dev);
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530896
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530897 u32 did_vid = tpm_read_did_vid(0);
898 if (did_vid > 0 && did_vid < 0xffffffff)
899 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
900 else
901 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_OFF);
902
Kevin Cody-Littlec97b5af2018-05-09 14:14:59 -0400903 u16 port = dev->path.pnp.port;
904
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530905 /* Resources */
906 acpigen_write_name("_CRS");
907 acpigen_write_resourcetemplate_header();
908 acpigen_write_mem32fixed(1, CONFIG_TPM_TIS_BASE_ADDRESS, 0x5000);
Frans Hendriks6cc937e2018-10-29 14:30:58 +0100909 if (port)
910 acpigen_write_io16(port, port, 1, 2, 1);
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530911
912 if (CONFIG_TPM_PIRQ) {
913 /*
914 * PIRQ: Update interrupt vector with configured PIRQ
915 * Active-Low Level-Triggered Shared
916 */
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800917 struct acpi_irq tpm_irq_a = ACPI_IRQ_LEVEL_LOW(CONFIG_TPM_PIRQ);
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530918 acpi_device_write_interrupt(&tpm_irq_a);
919 } else if (tpm_read_int_vector(0) > 0) {
920 u8 int_vec = tpm_read_int_vector(0);
921 u8 int_pol = tpm_read_int_polarity(0);
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800922 struct acpi_irq tpm_irq = ACPI_IRQ_LEVEL_LOW(int_vec);
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530923
924 if (int_pol & 1)
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800925 tpm_irq.polarity = ACPI_IRQ_ACTIVE_LOW;
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530926 else
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800927 tpm_irq.polarity = ACPI_IRQ_ACTIVE_HIGH;
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530928
929 if (int_pol & 2)
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800930 tpm_irq.mode = ACPI_IRQ_EDGE_TRIGGERED;
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530931 else
Furquan Shaikh5b9b5932017-02-21 13:16:30 -0800932 tpm_irq.mode = ACPI_IRQ_LEVEL_TRIGGERED;
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530933
934 acpi_device_write_interrupt(&tpm_irq);
935 }
936
937 acpigen_write_resourcetemplate_footer();
938
Julius Wernercd49cce2019-03-05 16:53:33 -0800939 if (!CONFIG(CHROMEOS)) {
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530940 /*
941 * _DSM method
942 */
943 struct dsm_uuid ids[] = {
944 /* Physical presence interface.
945 * This is used to submit commands like "Clear TPM" to
946 * be run at next reboot provided that user confirms
947 * them. Spec allows user to cancel all commands and/or
948 * configure BIOS to reject commands. So we pretend that
949 * user did just this: cancelled everything. If user
950 * really wants to clear TPM the only option now is to
951 * do it manually in payload.
952 */
953 DSM_UUID(TPM_PPI_UUID, &tpm_ppi_callbacks[0],
954 ARRAY_SIZE(tpm_ppi_callbacks), (void *) &arg),
955 /* Memory clearing on boot: just a dummy. */
956 DSM_UUID(TPM_MCI_UUID, &tpm_mci_callbacks[0],
957 ARRAY_SIZE(tpm_mci_callbacks), (void *) &arg),
958 };
959
960 acpigen_write_dsm_uuid_arr(ids, ARRAY_SIZE(ids));
961 }
962 acpigen_pop_len(); /* Device */
963 acpigen_pop_len(); /* Scope */
964
Kyösti Mälkkibaa16e92019-11-05 18:38:00 +0200965#if !DEVTREE_EARLY
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530966 printk(BIOS_INFO, "%s.%s: %s %s\n", path, acpi_device_name(dev),
967 dev->chip_ops->name, dev_path(dev));
Kyösti Mälkkibaa16e92019-11-05 18:38:00 +0200968#endif
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530969}
970
Aaron Durbinaa090cb2017-09-13 16:01:52 -0600971static const char *lpc_tpm_acpi_name(const struct device *dev)
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530972{
973 return "TPM";
974}
975#endif
976
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700977static struct device_operations lpc_tpm_ops = {
Elyes HAOUAS2aa3b162018-11-27 17:02:10 +0100978 .read_resources = lpc_tpm_read_resources,
979 .set_resources = lpc_tpm_set_resources,
Julius Wernercd49cce2019-03-05 16:53:33 -0800980#if CONFIG(HAVE_ACPI_TABLES)
Nico Huber68680dd2020-03-31 17:34:52 +0200981 .acpi_name = lpc_tpm_acpi_name,
982 .acpi_fill_ssdt = lpc_tpm_fill_ssdt,
Naresh G Solanki80ff0382016-11-15 11:01:33 +0530983#endif
Duncan Lauriedd281ed2014-10-30 15:20:19 -0700984};
985
986static struct pnp_info pnp_dev_info[] = {
987 { .flags = PNP_IRQ0 }
988};
989
990static void enable_dev(struct device *dev)
991{
992 pnp_enable_devices(dev, &lpc_tpm_ops,
993 ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
994}
995
996struct chip_operations drivers_pc80_tpm_ops = {
997 CHIP_NAME("LPC TPM")
998 .enable_dev = enable_dev
999};