]>
Commit | Line | Data |
---|---|---|
b886d83c | 1 | // SPDX-License-Identifier: GPL-2.0-only |
41a5e1cf CR |
2 | /* |
3 | * Copyright (C) 2005, 2006 IBM Corporation | |
4 | * Copyright (C) 2014, 2015 Intel Corporation | |
5 | * | |
6 | * Authors: | |
7 | * Leendert van Doorn <leendert@watson.ibm.com> | |
8 | * Kylene Hall <kjhall@us.ibm.com> | |
9 | * | |
10 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | |
11 | * | |
12 | * Device driver for TCG/TCPA TPM (trusted platform module). | |
13 | * Specifications at www.trustedcomputinggroup.org | |
14 | * | |
15 | * This device driver implements the TPM interface as defined in | |
16 | * the TCG TPM Interface Spec version 1.2, revision 1.0. | |
41a5e1cf CR |
17 | */ |
18 | #include <linux/init.h> | |
19 | #include <linux/module.h> | |
20 | #include <linux/moduleparam.h> | |
21 | #include <linux/pnp.h> | |
22 | #include <linux/slab.h> | |
23 | #include <linux/interrupt.h> | |
24 | #include <linux/wait.h> | |
25 | #include <linux/acpi.h> | |
26 | #include <linux/freezer.h> | |
27 | #include "tpm.h" | |
28 | #include "tpm_tis_core.h" | |
29 | ||
b3e958ce AS |
30 | static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value); |
31 | ||
87cdfdd1 NJ |
32 | static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, |
33 | bool check_cancel, bool *canceled) | |
34 | { | |
35 | u8 status = chip->ops->status(chip); | |
36 | ||
37 | *canceled = false; | |
38 | if ((status & mask) == mask) | |
39 | return true; | |
40 | if (check_cancel && chip->ops->req_canceled(chip, status)) { | |
41 | *canceled = true; | |
42 | return true; | |
43 | } | |
44 | return false; | |
45 | } | |
46 | ||
47 | static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, | |
48 | unsigned long timeout, wait_queue_head_t *queue, | |
49 | bool check_cancel) | |
50 | { | |
51 | unsigned long stop; | |
52 | long rc; | |
53 | u8 status; | |
54 | bool canceled = false; | |
55 | ||
56 | /* check current status */ | |
57 | status = chip->ops->status(chip); | |
58 | if ((status & mask) == mask) | |
59 | return 0; | |
60 | ||
61 | stop = jiffies + timeout; | |
62 | ||
63 | if (chip->flags & TPM_CHIP_FLAG_IRQ) { | |
64 | again: | |
65 | timeout = stop - jiffies; | |
66 | if ((long)timeout <= 0) | |
67 | return -ETIME; | |
68 | rc = wait_event_interruptible_timeout(*queue, | |
69 | wait_for_tpm_stat_cond(chip, mask, check_cancel, | |
70 | &canceled), | |
71 | timeout); | |
72 | if (rc > 0) { | |
73 | if (canceled) | |
74 | return -ECANCELED; | |
75 | return 0; | |
76 | } | |
77 | if (rc == -ERESTARTSYS && freezing(current)) { | |
78 | clear_thread_flag(TIF_SIGPENDING); | |
79 | goto again; | |
80 | } | |
81 | } else { | |
82 | do { | |
424eaf91 NJ |
83 | usleep_range(TPM_TIMEOUT_USECS_MIN, |
84 | TPM_TIMEOUT_USECS_MAX); | |
87cdfdd1 NJ |
85 | status = chip->ops->status(chip); |
86 | if ((status & mask) == mask) | |
87 | return 0; | |
88 | } while (time_before(jiffies, stop)); | |
89 | } | |
90 | return -ETIME; | |
91 | } | |
92 | ||
41a5e1cf CR |
93 | /* Before we attempt to access the TPM we must see that the valid bit is set. |
94 | * The specification says that this bit is 0 at reset and remains 0 until the | |
95 | * 'TPM has gone through its self test and initialization and has established | |
96 | * correct values in the other bits.' | |
97 | */ | |
98 | static int wait_startup(struct tpm_chip *chip, int l) | |
99 | { | |
100 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
101 | unsigned long stop = jiffies + chip->timeout_a; | |
102 | ||
103 | do { | |
104 | int rc; | |
105 | u8 access; | |
106 | ||
107 | rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access); | |
108 | if (rc < 0) | |
109 | return rc; | |
110 | ||
111 | if (access & TPM_ACCESS_VALID) | |
112 | return 0; | |
9f3fc7bc | 113 | tpm_msleep(TPM_TIMEOUT); |
41a5e1cf CR |
114 | } while (time_before(jiffies, stop)); |
115 | return -1; | |
116 | } | |
117 | ||
84d25940 | 118 | static bool check_locality(struct tpm_chip *chip, int l) |
41a5e1cf CR |
119 | { |
120 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
121 | int rc; | |
122 | u8 access; | |
123 | ||
124 | rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access); | |
125 | if (rc < 0) | |
84d25940 | 126 | return false; |
41a5e1cf CR |
127 | |
128 | if ((access & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == | |
84d25940 JS |
129 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { |
130 | priv->locality = l; | |
131 | return true; | |
132 | } | |
41a5e1cf | 133 | |
84d25940 | 134 | return false; |
41a5e1cf CR |
135 | } |
136 | ||
33bafe90 JS |
137 | static bool locality_inactive(struct tpm_chip *chip, int l) |
138 | { | |
139 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
140 | int rc; | |
141 | u8 access; | |
142 | ||
143 | rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access); | |
144 | if (rc < 0) | |
145 | return false; | |
146 | ||
147 | if ((access & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) | |
148 | == TPM_ACCESS_VALID) | |
149 | return true; | |
150 | ||
151 | return false; | |
152 | } | |
153 | ||
888d867d | 154 | static int release_locality(struct tpm_chip *chip, int l) |
41a5e1cf CR |
155 | { |
156 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
33bafe90 JS |
157 | unsigned long stop, timeout; |
158 | long rc; | |
41a5e1cf | 159 | |
e6aef069 | 160 | tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY); |
888d867d | 161 | |
33bafe90 JS |
162 | stop = jiffies + chip->timeout_a; |
163 | ||
164 | if (chip->flags & TPM_CHIP_FLAG_IRQ) { | |
165 | again: | |
166 | timeout = stop - jiffies; | |
167 | if ((long)timeout <= 0) | |
168 | return -1; | |
169 | ||
170 | rc = wait_event_interruptible_timeout(priv->int_queue, | |
171 | (locality_inactive(chip, l)), | |
172 | timeout); | |
173 | ||
174 | if (rc > 0) | |
175 | return 0; | |
176 | ||
177 | if (rc == -ERESTARTSYS && freezing(current)) { | |
178 | clear_thread_flag(TIF_SIGPENDING); | |
179 | goto again; | |
180 | } | |
181 | } else { | |
182 | do { | |
183 | if (locality_inactive(chip, l)) | |
184 | return 0; | |
185 | tpm_msleep(TPM_TIMEOUT); | |
186 | } while (time_before(jiffies, stop)); | |
187 | } | |
188 | return -1; | |
41a5e1cf CR |
189 | } |
190 | ||
191 | static int request_locality(struct tpm_chip *chip, int l) | |
192 | { | |
193 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
194 | unsigned long stop, timeout; | |
195 | long rc; | |
196 | ||
84d25940 | 197 | if (check_locality(chip, l)) |
41a5e1cf CR |
198 | return l; |
199 | ||
200 | rc = tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_REQUEST_USE); | |
201 | if (rc < 0) | |
202 | return rc; | |
203 | ||
204 | stop = jiffies + chip->timeout_a; | |
205 | ||
206 | if (chip->flags & TPM_CHIP_FLAG_IRQ) { | |
207 | again: | |
208 | timeout = stop - jiffies; | |
209 | if ((long)timeout <= 0) | |
210 | return -1; | |
211 | rc = wait_event_interruptible_timeout(priv->int_queue, | |
212 | (check_locality | |
84d25940 | 213 | (chip, l)), |
41a5e1cf CR |
214 | timeout); |
215 | if (rc > 0) | |
216 | return l; | |
217 | if (rc == -ERESTARTSYS && freezing(current)) { | |
218 | clear_thread_flag(TIF_SIGPENDING); | |
219 | goto again; | |
220 | } | |
221 | } else { | |
222 | /* wait for burstcount */ | |
223 | do { | |
84d25940 | 224 | if (check_locality(chip, l)) |
41a5e1cf | 225 | return l; |
9f3fc7bc | 226 | tpm_msleep(TPM_TIMEOUT); |
41a5e1cf CR |
227 | } while (time_before(jiffies, stop)); |
228 | } | |
229 | return -1; | |
230 | } | |
231 | ||
232 | static u8 tpm_tis_status(struct tpm_chip *chip) | |
233 | { | |
234 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
235 | int rc; | |
236 | u8 status; | |
237 | ||
238 | rc = tpm_tis_read8(priv, TPM_STS(priv->locality), &status); | |
239 | if (rc < 0) | |
240 | return 0; | |
241 | ||
242 | return status; | |
243 | } | |
244 | ||
245 | static void tpm_tis_ready(struct tpm_chip *chip) | |
246 | { | |
247 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
248 | ||
249 | /* this causes the current command to be aborted */ | |
250 | tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_COMMAND_READY); | |
251 | } | |
252 | ||
253 | static int get_burstcount(struct tpm_chip *chip) | |
254 | { | |
255 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
256 | unsigned long stop; | |
257 | int burstcnt, rc; | |
9754d45e | 258 | u32 value; |
41a5e1cf CR |
259 | |
260 | /* wait for burstcount */ | |
302a6ad7 AS |
261 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
262 | stop = jiffies + chip->timeout_a; | |
263 | else | |
264 | stop = jiffies + chip->timeout_d; | |
41a5e1cf | 265 | do { |
9754d45e | 266 | rc = tpm_tis_read32(priv, TPM_STS(priv->locality), &value); |
41a5e1cf CR |
267 | if (rc < 0) |
268 | return rc; | |
269 | ||
9754d45e | 270 | burstcnt = (value >> 8) & 0xFFFF; |
41a5e1cf CR |
271 | if (burstcnt) |
272 | return burstcnt; | |
424eaf91 | 273 | usleep_range(TPM_TIMEOUT_USECS_MIN, TPM_TIMEOUT_USECS_MAX); |
41a5e1cf CR |
274 | } while (time_before(jiffies, stop)); |
275 | return -EBUSY; | |
276 | } | |
277 | ||
278 | static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) | |
279 | { | |
280 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
281 | int size = 0, burstcnt, rc; | |
282 | ||
2c97f6f2 PH |
283 | while (size < count) { |
284 | rc = wait_for_tpm_stat(chip, | |
41a5e1cf CR |
285 | TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
286 | chip->timeout_c, | |
2c97f6f2 PH |
287 | &priv->read_queue, true); |
288 | if (rc < 0) | |
289 | return rc; | |
26a137e3 JZ |
290 | burstcnt = get_burstcount(chip); |
291 | if (burstcnt < 0) { | |
292 | dev_err(&chip->dev, "Unable to read burstcount\n"); | |
293 | return burstcnt; | |
294 | } | |
295 | burstcnt = min_t(int, burstcnt, count - size); | |
41a5e1cf CR |
296 | |
297 | rc = tpm_tis_read_bytes(priv, TPM_DATA_FIFO(priv->locality), | |
298 | burstcnt, buf + size); | |
299 | if (rc < 0) | |
300 | return rc; | |
301 | ||
302 | size += burstcnt; | |
303 | } | |
304 | return size; | |
305 | } | |
306 | ||
307 | static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |
308 | { | |
309 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
310 | int size = 0; | |
6bb320ca JB |
311 | int status; |
312 | u32 expected; | |
41a5e1cf CR |
313 | |
314 | if (count < TPM_HEADER_SIZE) { | |
315 | size = -EIO; | |
316 | goto out; | |
317 | } | |
318 | ||
319 | size = recv_data(chip, buf, TPM_HEADER_SIZE); | |
320 | /* read first 10 bytes, including tag, paramsize, and result */ | |
321 | if (size < TPM_HEADER_SIZE) { | |
322 | dev_err(&chip->dev, "Unable to read header\n"); | |
323 | goto out; | |
324 | } | |
325 | ||
326 | expected = be32_to_cpu(*(__be32 *) (buf + 2)); | |
6bb320ca | 327 | if (expected > count || expected < TPM_HEADER_SIZE) { |
41a5e1cf CR |
328 | size = -EIO; |
329 | goto out; | |
330 | } | |
331 | ||
332 | size += recv_data(chip, &buf[TPM_HEADER_SIZE], | |
333 | expected - TPM_HEADER_SIZE); | |
334 | if (size < expected) { | |
335 | dev_err(&chip->dev, "Unable to read remainder of result\n"); | |
336 | size = -ETIME; | |
337 | goto out; | |
338 | } | |
339 | ||
2c97f6f2 PH |
340 | if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, |
341 | &priv->int_queue, false) < 0) { | |
342 | size = -ETIME; | |
343 | goto out; | |
344 | } | |
41a5e1cf CR |
345 | status = tpm_tis_status(chip); |
346 | if (status & TPM_STS_DATA_AVAIL) { /* retry? */ | |
347 | dev_err(&chip->dev, "Error left over data\n"); | |
348 | size = -EIO; | |
349 | goto out; | |
350 | } | |
351 | ||
352 | out: | |
353 | tpm_tis_ready(chip); | |
41a5e1cf CR |
354 | return size; |
355 | } | |
356 | ||
357 | /* | |
358 | * If interrupts are used (signaled by an irq set in the vendor structure) | |
359 | * tpm.c can skip polling for the data to be available as the interrupt is | |
360 | * waited for here | |
361 | */ | |
c37fbc09 | 362 | static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len) |
41a5e1cf CR |
363 | { |
364 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
365 | int rc, status, burstcnt; | |
366 | size_t count = 0; | |
1d70fe9d | 367 | bool itpm = priv->flags & TPM_TIS_ITPM_WORKAROUND; |
41a5e1cf | 368 | |
41a5e1cf CR |
369 | status = tpm_tis_status(chip); |
370 | if ((status & TPM_STS_COMMAND_READY) == 0) { | |
371 | tpm_tis_ready(chip); | |
372 | if (wait_for_tpm_stat | |
373 | (chip, TPM_STS_COMMAND_READY, chip->timeout_b, | |
374 | &priv->int_queue, false) < 0) { | |
375 | rc = -ETIME; | |
376 | goto out_err; | |
377 | } | |
378 | } | |
379 | ||
380 | while (count < len - 1) { | |
26a137e3 JZ |
381 | burstcnt = get_burstcount(chip); |
382 | if (burstcnt < 0) { | |
383 | dev_err(&chip->dev, "Unable to read burstcount\n"); | |
384 | rc = burstcnt; | |
385 | goto out_err; | |
386 | } | |
387 | burstcnt = min_t(int, burstcnt, len - count - 1); | |
41a5e1cf CR |
388 | rc = tpm_tis_write_bytes(priv, TPM_DATA_FIFO(priv->locality), |
389 | burstcnt, buf + count); | |
390 | if (rc < 0) | |
391 | goto out_err; | |
392 | ||
393 | count += burstcnt; | |
394 | ||
2c97f6f2 PH |
395 | if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, |
396 | &priv->int_queue, false) < 0) { | |
397 | rc = -ETIME; | |
398 | goto out_err; | |
399 | } | |
41a5e1cf CR |
400 | status = tpm_tis_status(chip); |
401 | if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) { | |
402 | rc = -EIO; | |
403 | goto out_err; | |
404 | } | |
405 | } | |
406 | ||
407 | /* write last byte */ | |
408 | rc = tpm_tis_write8(priv, TPM_DATA_FIFO(priv->locality), buf[count]); | |
409 | if (rc < 0) | |
410 | goto out_err; | |
411 | ||
2c97f6f2 PH |
412 | if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, |
413 | &priv->int_queue, false) < 0) { | |
414 | rc = -ETIME; | |
415 | goto out_err; | |
416 | } | |
41a5e1cf CR |
417 | status = tpm_tis_status(chip); |
418 | if (!itpm && (status & TPM_STS_DATA_EXPECT) != 0) { | |
419 | rc = -EIO; | |
420 | goto out_err; | |
421 | } | |
422 | ||
423 | return 0; | |
424 | ||
425 | out_err: | |
426 | tpm_tis_ready(chip); | |
41a5e1cf CR |
427 | return rc; |
428 | } | |
429 | ||
430 | static void disable_interrupts(struct tpm_chip *chip) | |
431 | { | |
432 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
433 | u32 intmask; | |
434 | int rc; | |
435 | ||
b160c94b JS |
436 | if (priv->irq == 0) |
437 | return; | |
438 | ||
41a5e1cf CR |
439 | rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask); |
440 | if (rc < 0) | |
441 | intmask = 0; | |
442 | ||
443 | intmask &= ~TPM_GLOBAL_INT_ENABLE; | |
444 | rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); | |
445 | ||
446 | devm_free_irq(chip->dev.parent, priv->irq, chip); | |
447 | priv->irq = 0; | |
448 | chip->flags &= ~TPM_CHIP_FLAG_IRQ; | |
449 | } | |
450 | ||
451 | /* | |
452 | * If interrupts are used (signaled by an irq set in the vendor structure) | |
453 | * tpm.c can skip polling for the data to be available as the interrupt is | |
454 | * waited for here | |
455 | */ | |
c37fbc09 | 456 | static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len) |
41a5e1cf CR |
457 | { |
458 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
459 | int rc; | |
460 | u32 ordinal; | |
461 | unsigned long dur; | |
462 | ||
463 | rc = tpm_tis_send_data(chip, buf, len); | |
464 | if (rc < 0) | |
465 | return rc; | |
466 | ||
467 | /* go and do it */ | |
468 | rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO); | |
469 | if (rc < 0) | |
470 | goto out_err; | |
471 | ||
472 | if (chip->flags & TPM_CHIP_FLAG_IRQ) { | |
473 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); | |
474 | ||
d856c00f | 475 | dur = tpm_calc_ordinal_duration(chip, ordinal); |
41a5e1cf CR |
476 | if (wait_for_tpm_stat |
477 | (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur, | |
478 | &priv->read_queue, false) < 0) { | |
479 | rc = -ETIME; | |
480 | goto out_err; | |
481 | } | |
482 | } | |
f5595f5b | 483 | return 0; |
41a5e1cf CR |
484 | out_err: |
485 | tpm_tis_ready(chip); | |
41a5e1cf CR |
486 | return rc; |
487 | } | |
488 | ||
489 | static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) | |
490 | { | |
491 | int rc, irq; | |
492 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
493 | ||
494 | if (!(chip->flags & TPM_CHIP_FLAG_IRQ) || priv->irq_tested) | |
495 | return tpm_tis_send_main(chip, buf, len); | |
496 | ||
497 | /* Verify receipt of the expected IRQ */ | |
498 | irq = priv->irq; | |
499 | priv->irq = 0; | |
500 | chip->flags &= ~TPM_CHIP_FLAG_IRQ; | |
501 | rc = tpm_tis_send_main(chip, buf, len); | |
502 | priv->irq = irq; | |
503 | chip->flags |= TPM_CHIP_FLAG_IRQ; | |
504 | if (!priv->irq_tested) | |
9f3fc7bc | 505 | tpm_msleep(1); |
41a5e1cf CR |
506 | if (!priv->irq_tested) |
507 | disable_interrupts(chip); | |
508 | priv->irq_tested = true; | |
509 | return rc; | |
510 | } | |
511 | ||
5af4f1d5 JS |
512 | struct tis_vendor_durations_override { |
513 | u32 did_vid; | |
514 | struct tpm1_version version; | |
515 | unsigned long durations[3]; | |
516 | }; | |
517 | ||
518 | static const struct tis_vendor_durations_override vendor_dur_overrides[] = { | |
519 | /* STMicroelectronics 0x104a */ | |
520 | { 0x0000104a, | |
521 | { 1, 2, 8, 28 }, | |
522 | { (2 * 60 * HZ), (2 * 60 * HZ), (2 * 60 * HZ) } }, | |
523 | }; | |
524 | ||
525 | static void tpm_tis_update_durations(struct tpm_chip *chip, | |
526 | unsigned long *duration_cap) | |
527 | { | |
528 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
529 | struct tpm1_version *version; | |
530 | u32 did_vid; | |
531 | int i, rc; | |
532 | cap_t cap; | |
533 | ||
534 | chip->duration_adjusted = false; | |
535 | ||
536 | if (chip->ops->clk_enable != NULL) | |
537 | chip->ops->clk_enable(chip, true); | |
538 | ||
539 | rc = tpm_tis_read32(priv, TPM_DID_VID(0), &did_vid); | |
540 | if (rc < 0) { | |
541 | dev_warn(&chip->dev, "%s: failed to read did_vid. %d\n", | |
542 | __func__, rc); | |
543 | goto out; | |
544 | } | |
545 | ||
546 | /* Try to get a TPM version 1.2 or 1.1 TPM_CAP_VERSION_INFO */ | |
547 | rc = tpm1_getcap(chip, TPM_CAP_VERSION_1_2, &cap, | |
548 | "attempting to determine the 1.2 version", | |
549 | sizeof(cap.version2)); | |
550 | if (!rc) { | |
551 | version = &cap.version2.version; | |
552 | } else { | |
553 | rc = tpm1_getcap(chip, TPM_CAP_VERSION_1_1, &cap, | |
554 | "attempting to determine the 1.1 version", | |
555 | sizeof(cap.version1)); | |
556 | ||
557 | if (rc) | |
558 | goto out; | |
559 | ||
560 | version = &cap.version1; | |
561 | } | |
562 | ||
563 | for (i = 0; i != ARRAY_SIZE(vendor_dur_overrides); i++) { | |
564 | if (vendor_dur_overrides[i].did_vid != did_vid) | |
565 | continue; | |
566 | ||
567 | if ((version->major == | |
568 | vendor_dur_overrides[i].version.major) && | |
569 | (version->minor == | |
570 | vendor_dur_overrides[i].version.minor) && | |
571 | (version->rev_major == | |
572 | vendor_dur_overrides[i].version.rev_major) && | |
573 | (version->rev_minor == | |
574 | vendor_dur_overrides[i].version.rev_minor)) { | |
575 | ||
576 | memcpy(duration_cap, | |
577 | vendor_dur_overrides[i].durations, | |
578 | sizeof(vendor_dur_overrides[i].durations)); | |
579 | ||
580 | chip->duration_adjusted = true; | |
581 | goto out; | |
582 | } | |
583 | } | |
584 | ||
585 | out: | |
586 | if (chip->ops->clk_enable != NULL) | |
587 | chip->ops->clk_enable(chip, false); | |
588 | } | |
589 | ||
41a5e1cf CR |
590 | struct tis_vendor_timeout_override { |
591 | u32 did_vid; | |
592 | unsigned long timeout_us[4]; | |
593 | }; | |
594 | ||
595 | static const struct tis_vendor_timeout_override vendor_timeout_overrides[] = { | |
596 | /* Atmel 3204 */ | |
597 | { 0x32041114, { (TIS_SHORT_TIMEOUT*1000), (TIS_LONG_TIMEOUT*1000), | |
598 | (TIS_SHORT_TIMEOUT*1000), (TIS_SHORT_TIMEOUT*1000) } }, | |
599 | }; | |
600 | ||
36ce0897 | 601 | static void tpm_tis_update_timeouts(struct tpm_chip *chip, |
41a5e1cf CR |
602 | unsigned long *timeout_cap) |
603 | { | |
604 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
605 | int i, rc; | |
606 | u32 did_vid; | |
607 | ||
36ce0897 JS |
608 | chip->timeout_adjusted = false; |
609 | ||
b3e958ce AS |
610 | if (chip->ops->clk_enable != NULL) |
611 | chip->ops->clk_enable(chip, true); | |
612 | ||
41a5e1cf | 613 | rc = tpm_tis_read32(priv, TPM_DID_VID(0), &did_vid); |
36ce0897 JS |
614 | if (rc < 0) { |
615 | dev_warn(&chip->dev, "%s: failed to read did_vid: %d\n", | |
616 | __func__, rc); | |
b3e958ce | 617 | goto out; |
36ce0897 | 618 | } |
41a5e1cf CR |
619 | |
620 | for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) { | |
621 | if (vendor_timeout_overrides[i].did_vid != did_vid) | |
622 | continue; | |
623 | memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us, | |
624 | sizeof(vendor_timeout_overrides[i].timeout_us)); | |
36ce0897 | 625 | chip->timeout_adjusted = true; |
41a5e1cf CR |
626 | } |
627 | ||
b3e958ce AS |
628 | out: |
629 | if (chip->ops->clk_enable != NULL) | |
630 | chip->ops->clk_enable(chip, false); | |
631 | ||
36ce0897 | 632 | return; |
41a5e1cf CR |
633 | } |
634 | ||
635 | /* | |
636 | * Early probing for iTPM with STS_DATA_EXPECT flaw. | |
637 | * Try sending command without itpm flag set and if that | |
638 | * fails, repeat with itpm flag set. | |
639 | */ | |
640 | static int probe_itpm(struct tpm_chip *chip) | |
641 | { | |
642 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
643 | int rc = 0; | |
0bbc931a | 644 | static const u8 cmd_getticks[] = { |
41a5e1cf CR |
645 | 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, |
646 | 0x00, 0x00, 0x00, 0xf1 | |
647 | }; | |
648 | size_t len = sizeof(cmd_getticks); | |
41a5e1cf CR |
649 | u16 vendor; |
650 | ||
419a16d9 MS |
651 | if (priv->flags & TPM_TIS_ITPM_WORKAROUND) |
652 | return 0; | |
653 | ||
41a5e1cf CR |
654 | rc = tpm_tis_read16(priv, TPM_DID_VID(0), &vendor); |
655 | if (rc < 0) | |
656 | return rc; | |
657 | ||
658 | /* probe only iTPMS */ | |
659 | if (vendor != TPM_VID_INTEL) | |
660 | return 0; | |
661 | ||
e6aef069 JS |
662 | if (request_locality(chip, 0) != 0) |
663 | return -EBUSY; | |
664 | ||
41a5e1cf CR |
665 | rc = tpm_tis_send_data(chip, cmd_getticks, len); |
666 | if (rc == 0) | |
667 | goto out; | |
668 | ||
669 | tpm_tis_ready(chip); | |
41a5e1cf | 670 | |
419a16d9 MS |
671 | priv->flags |= TPM_TIS_ITPM_WORKAROUND; |
672 | ||
41a5e1cf | 673 | rc = tpm_tis_send_data(chip, cmd_getticks, len); |
419a16d9 | 674 | if (rc == 0) |
41a5e1cf | 675 | dev_info(&chip->dev, "Detected an iTPM.\n"); |
419a16d9 MS |
676 | else { |
677 | priv->flags &= ~TPM_TIS_ITPM_WORKAROUND; | |
41a5e1cf | 678 | rc = -EFAULT; |
419a16d9 | 679 | } |
41a5e1cf CR |
680 | |
681 | out: | |
682 | tpm_tis_ready(chip); | |
e6aef069 | 683 | release_locality(chip, priv->locality); |
41a5e1cf CR |
684 | |
685 | return rc; | |
686 | } | |
687 | ||
688 | static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status) | |
689 | { | |
690 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
691 | ||
692 | switch (priv->manufacturer_id) { | |
693 | case TPM_VID_WINBOND: | |
694 | return ((status == TPM_STS_VALID) || | |
695 | (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY))); | |
696 | case TPM_VID_STM: | |
697 | return (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)); | |
698 | default: | |
699 | return (status == TPM_STS_COMMAND_READY); | |
700 | } | |
701 | } | |
702 | ||
703 | static irqreturn_t tis_int_handler(int dummy, void *dev_id) | |
704 | { | |
705 | struct tpm_chip *chip = dev_id; | |
706 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
707 | u32 interrupt; | |
708 | int i, rc; | |
709 | ||
710 | rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt); | |
711 | if (rc < 0) | |
712 | return IRQ_NONE; | |
713 | ||
714 | if (interrupt == 0) | |
715 | return IRQ_NONE; | |
716 | ||
717 | priv->irq_tested = true; | |
718 | if (interrupt & TPM_INTF_DATA_AVAIL_INT) | |
719 | wake_up_interruptible(&priv->read_queue); | |
720 | if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT) | |
721 | for (i = 0; i < 5; i++) | |
84d25940 | 722 | if (check_locality(chip, i)) |
41a5e1cf CR |
723 | break; |
724 | if (interrupt & | |
725 | (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT | | |
726 | TPM_INTF_CMD_READY_INT)) | |
727 | wake_up_interruptible(&priv->int_queue); | |
728 | ||
729 | /* Clear interrupts handled with TPM_EOI */ | |
730 | rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), interrupt); | |
731 | if (rc < 0) | |
732 | return IRQ_NONE; | |
733 | ||
734 | tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &interrupt); | |
735 | return IRQ_HANDLED; | |
736 | } | |
737 | ||
eb5854e7 JS |
738 | static int tpm_tis_gen_interrupt(struct tpm_chip *chip) |
739 | { | |
740 | const char *desc = "attempting to generate an interrupt"; | |
741 | u32 cap2; | |
742 | cap_t cap; | |
743 | ||
744 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | |
745 | return tpm2_get_tpm_pt(chip, 0x100, &cap2, desc); | |
746 | else | |
f4d916b7 | 747 | return tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, |
c659af78 | 748 | 0); |
eb5854e7 JS |
749 | } |
750 | ||
41a5e1cf CR |
751 | /* Register the IRQ and issue a command that will cause an interrupt. If an |
752 | * irq is seen then leave the chip setup for IRQ operation, otherwise reverse | |
753 | * everything and leave in polling mode. Returns 0 on success. | |
754 | */ | |
755 | static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask, | |
756 | int flags, int irq) | |
757 | { | |
758 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
759 | u8 original_int_vec; | |
760 | int rc; | |
761 | u32 int_status; | |
762 | ||
763 | if (devm_request_irq(chip->dev.parent, irq, tis_int_handler, flags, | |
764 | dev_name(&chip->dev), chip) != 0) { | |
765 | dev_info(&chip->dev, "Unable to request irq: %d for probe\n", | |
766 | irq); | |
767 | return -1; | |
768 | } | |
769 | priv->irq = irq; | |
770 | ||
771 | rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality), | |
772 | &original_int_vec); | |
773 | if (rc < 0) | |
774 | return rc; | |
775 | ||
776 | rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), irq); | |
777 | if (rc < 0) | |
778 | return rc; | |
779 | ||
780 | rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &int_status); | |
781 | if (rc < 0) | |
782 | return rc; | |
783 | ||
784 | /* Clear all existing */ | |
785 | rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), int_status); | |
786 | if (rc < 0) | |
787 | return rc; | |
788 | ||
789 | /* Turn on */ | |
790 | rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), | |
791 | intmask | TPM_GLOBAL_INT_ENABLE); | |
792 | if (rc < 0) | |
793 | return rc; | |
794 | ||
795 | priv->irq_tested = false; | |
796 | ||
797 | /* Generate an interrupt by having the core call through to | |
798 | * tpm_tis_send | |
799 | */ | |
eb5854e7 JS |
800 | rc = tpm_tis_gen_interrupt(chip); |
801 | if (rc < 0) | |
802 | return rc; | |
41a5e1cf CR |
803 | |
804 | /* tpm_tis_send will either confirm the interrupt is working or it | |
805 | * will call disable_irq which undoes all of the above. | |
806 | */ | |
807 | if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) { | |
808 | rc = tpm_tis_write8(priv, original_int_vec, | |
809 | TPM_INT_VECTOR(priv->locality)); | |
810 | if (rc < 0) | |
811 | return rc; | |
812 | ||
813 | return 1; | |
814 | } | |
815 | ||
816 | return 0; | |
817 | } | |
818 | ||
819 | /* Try to find the IRQ the TPM is using. This is for legacy x86 systems that | |
820 | * do not have ACPI/etc. We typically expect the interrupt to be declared if | |
821 | * present. | |
822 | */ | |
823 | static void tpm_tis_probe_irq(struct tpm_chip *chip, u32 intmask) | |
824 | { | |
825 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
826 | u8 original_int_vec; | |
827 | int i, rc; | |
828 | ||
829 | rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality), | |
830 | &original_int_vec); | |
831 | if (rc < 0) | |
832 | return; | |
833 | ||
834 | if (!original_int_vec) { | |
835 | if (IS_ENABLED(CONFIG_X86)) | |
836 | for (i = 3; i <= 15; i++) | |
837 | if (!tpm_tis_probe_irq_single(chip, intmask, 0, | |
838 | i)) | |
839 | return; | |
840 | } else if (!tpm_tis_probe_irq_single(chip, intmask, 0, | |
841 | original_int_vec)) | |
842 | return; | |
843 | } | |
844 | ||
845 | void tpm_tis_remove(struct tpm_chip *chip) | |
846 | { | |
847 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
848 | u32 reg = TPM_INT_ENABLE(priv->locality); | |
849 | u32 interrupt; | |
850 | int rc; | |
851 | ||
b3e958ce AS |
852 | tpm_tis_clkrun_enable(chip, true); |
853 | ||
41a5e1cf CR |
854 | rc = tpm_tis_read32(priv, reg, &interrupt); |
855 | if (rc < 0) | |
856 | interrupt = 0; | |
857 | ||
858 | tpm_tis_write32(priv, reg, ~TPM_GLOBAL_INT_ENABLE & interrupt); | |
b3e958ce AS |
859 | |
860 | tpm_tis_clkrun_enable(chip, false); | |
861 | ||
862 | if (priv->ilb_base_addr) | |
863 | iounmap(priv->ilb_base_addr); | |
41a5e1cf CR |
864 | } |
865 | EXPORT_SYMBOL_GPL(tpm_tis_remove); | |
866 | ||
b3e958ce AS |
867 | /** |
868 | * tpm_tis_clkrun_enable() - Keep clkrun protocol disabled for entire duration | |
869 | * of a single TPM command | |
870 | * @chip: TPM chip to use | |
871 | * @value: 1 - Disable CLKRUN protocol, so that clocks are free running | |
872 | * 0 - Enable CLKRUN protocol | |
873 | * Call this function directly in tpm_tis_remove() in error or driver removal | |
874 | * path, since the chip->ops is set to NULL in tpm_chip_unregister(). | |
875 | */ | |
876 | static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value) | |
877 | { | |
878 | struct tpm_tis_data *data = dev_get_drvdata(&chip->dev); | |
879 | u32 clkrun_val; | |
880 | ||
6c9f0ce0 JMC |
881 | if (!IS_ENABLED(CONFIG_X86) || !is_bsw() || |
882 | !data->ilb_base_addr) | |
b3e958ce AS |
883 | return; |
884 | ||
885 | if (value) { | |
b3e958ce AS |
886 | data->clkrun_enabled++; |
887 | if (data->clkrun_enabled > 1) | |
888 | return; | |
889 | clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); | |
890 | ||
891 | /* Disable LPC CLKRUN# */ | |
892 | clkrun_val &= ~LPC_CLKRUN_EN; | |
893 | iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); | |
894 | ||
895 | /* | |
896 | * Write any random value on port 0x80 which is on LPC, to make | |
897 | * sure LPC clock is running before sending any TPM command. | |
898 | */ | |
899 | outb(0xCC, 0x80); | |
900 | } else { | |
901 | data->clkrun_enabled--; | |
902 | if (data->clkrun_enabled) | |
903 | return; | |
904 | ||
905 | clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); | |
906 | ||
907 | /* Enable LPC CLKRUN# */ | |
908 | clkrun_val |= LPC_CLKRUN_EN; | |
909 | iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); | |
910 | ||
911 | /* | |
912 | * Write any random value on port 0x80 which is on LPC, to make | |
913 | * sure LPC clock is running before sending any TPM command. | |
914 | */ | |
915 | outb(0xCC, 0x80); | |
b3e958ce AS |
916 | } |
917 | } | |
918 | ||
41a5e1cf | 919 | static const struct tpm_class_ops tpm_tis = { |
cae8b441 | 920 | .flags = TPM_OPS_AUTO_STARTUP, |
41a5e1cf CR |
921 | .status = tpm_tis_status, |
922 | .recv = tpm_tis_recv, | |
923 | .send = tpm_tis_send, | |
924 | .cancel = tpm_tis_ready, | |
925 | .update_timeouts = tpm_tis_update_timeouts, | |
5af4f1d5 | 926 | .update_durations = tpm_tis_update_durations, |
41a5e1cf CR |
927 | .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
928 | .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, | |
929 | .req_canceled = tpm_tis_req_canceled, | |
e6aef069 JS |
930 | .request_locality = request_locality, |
931 | .relinquish_locality = release_locality, | |
b3e958ce | 932 | .clk_enable = tpm_tis_clkrun_enable, |
41a5e1cf CR |
933 | }; |
934 | ||
935 | int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, | |
936 | const struct tpm_tis_phy_ops *phy_ops, | |
937 | acpi_handle acpi_dev_handle) | |
938 | { | |
5fc0bead JMC |
939 | u32 vendor; |
940 | u32 intfcaps; | |
941 | u32 intmask; | |
6c9f0ce0 | 942 | u32 clkrun_val; |
41a5e1cf CR |
943 | u8 rid; |
944 | int rc, probe; | |
945 | struct tpm_chip *chip; | |
946 | ||
947 | chip = tpmm_chip_alloc(dev, &tpm_tis); | |
948 | if (IS_ERR(chip)) | |
949 | return PTR_ERR(chip); | |
950 | ||
951 | #ifdef CONFIG_ACPI | |
952 | chip->acpi_dev_handle = acpi_dev_handle; | |
953 | #endif | |
954 | ||
7a64c559 LC |
955 | chip->hwrng.quality = priv->rng_quality; |
956 | ||
41a5e1cf | 957 | /* Maximum timeouts */ |
79b591c0 | 958 | chip->timeout_a = msecs_to_jiffies(TIS_TIMEOUT_A_MAX); |
959 | chip->timeout_b = msecs_to_jiffies(TIS_TIMEOUT_B_MAX); | |
960 | chip->timeout_c = msecs_to_jiffies(TIS_TIMEOUT_C_MAX); | |
961 | chip->timeout_d = msecs_to_jiffies(TIS_TIMEOUT_D_MAX); | |
41a5e1cf CR |
962 | priv->phy_ops = phy_ops; |
963 | dev_set_drvdata(&chip->dev, priv); | |
964 | ||
c382babc AS |
965 | if (is_bsw()) { |
966 | priv->ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR, | |
967 | ILB_REMAP_SIZE); | |
968 | if (!priv->ilb_base_addr) | |
969 | return -ENOMEM; | |
6c9f0ce0 JMC |
970 | |
971 | clkrun_val = ioread32(priv->ilb_base_addr + LPC_CNTRL_OFFSET); | |
972 | /* Check if CLKRUN# is already not enabled in the LPC bus */ | |
973 | if (!(clkrun_val & LPC_CLKRUN_EN)) { | |
974 | iounmap(priv->ilb_base_addr); | |
975 | priv->ilb_base_addr = NULL; | |
976 | } | |
c382babc AS |
977 | } |
978 | ||
b3e958ce AS |
979 | if (chip->ops->clk_enable != NULL) |
980 | chip->ops->clk_enable(chip, true); | |
981 | ||
41a5e1cf CR |
982 | if (wait_startup(chip, 0) != 0) { |
983 | rc = -ENODEV; | |
9550f210 | 984 | goto out_err; |
41a5e1cf CR |
985 | } |
986 | ||
987 | /* Take control of the TPM's interrupt hardware and shut it off */ | |
988 | rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask); | |
989 | if (rc < 0) | |
9550f210 | 990 | goto out_err; |
41a5e1cf CR |
991 | |
992 | intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT | | |
993 | TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT; | |
994 | intmask &= ~TPM_GLOBAL_INT_ENABLE; | |
995 | tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); | |
996 | ||
47a6c28b | 997 | rc = tpm_chip_start(chip); |
a3fbfae8 | 998 | if (rc) |
9550f210 | 999 | goto out_err; |
41a5e1cf | 1000 | rc = tpm2_probe(chip); |
9550f210 | 1001 | tpm_chip_stop(chip); |
41a5e1cf | 1002 | if (rc) |
9550f210 | 1003 | goto out_err; |
41a5e1cf CR |
1004 | |
1005 | rc = tpm_tis_read32(priv, TPM_DID_VID(0), &vendor); | |
1006 | if (rc < 0) | |
9550f210 | 1007 | goto out_err; |
41a5e1cf CR |
1008 | |
1009 | priv->manufacturer_id = vendor; | |
1010 | ||
1011 | rc = tpm_tis_read8(priv, TPM_RID(0), &rid); | |
1012 | if (rc < 0) | |
9550f210 | 1013 | goto out_err; |
41a5e1cf CR |
1014 | |
1015 | dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n", | |
1016 | (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2", | |
1017 | vendor >> 16, rid); | |
1018 | ||
419a16d9 MS |
1019 | probe = probe_itpm(chip); |
1020 | if (probe < 0) { | |
1021 | rc = -ENODEV; | |
9550f210 | 1022 | goto out_err; |
41a5e1cf CR |
1023 | } |
1024 | ||
1025 | /* Figure out the capabilities */ | |
1026 | rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps); | |
1027 | if (rc < 0) | |
9550f210 | 1028 | goto out_err; |
41a5e1cf CR |
1029 | |
1030 | dev_dbg(dev, "TPM interface capabilities (0x%x):\n", | |
1031 | intfcaps); | |
1032 | if (intfcaps & TPM_INTF_BURST_COUNT_STATIC) | |
1033 | dev_dbg(dev, "\tBurst Count Static\n"); | |
1034 | if (intfcaps & TPM_INTF_CMD_READY_INT) | |
1035 | dev_dbg(dev, "\tCommand Ready Int Support\n"); | |
1036 | if (intfcaps & TPM_INTF_INT_EDGE_FALLING) | |
1037 | dev_dbg(dev, "\tInterrupt Edge Falling\n"); | |
1038 | if (intfcaps & TPM_INTF_INT_EDGE_RISING) | |
1039 | dev_dbg(dev, "\tInterrupt Edge Rising\n"); | |
1040 | if (intfcaps & TPM_INTF_INT_LEVEL_LOW) | |
1041 | dev_dbg(dev, "\tInterrupt Level Low\n"); | |
1042 | if (intfcaps & TPM_INTF_INT_LEVEL_HIGH) | |
1043 | dev_dbg(dev, "\tInterrupt Level High\n"); | |
1044 | if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) | |
1045 | dev_dbg(dev, "\tLocality Change Int Support\n"); | |
1046 | if (intfcaps & TPM_INTF_STS_VALID_INT) | |
1047 | dev_dbg(dev, "\tSts Valid Int Support\n"); | |
1048 | if (intfcaps & TPM_INTF_DATA_AVAIL_INT) | |
1049 | dev_dbg(dev, "\tData Avail Int Support\n"); | |
1050 | ||
41a5e1cf CR |
1051 | /* INTERRUPT Setup */ |
1052 | init_waitqueue_head(&priv->read_queue); | |
1053 | init_waitqueue_head(&priv->int_queue); | |
1054 | if (irq != -1) { | |
d1d253cf JG |
1055 | /* Before doing irq testing issue a command to the TPM in polling mode |
1056 | * to make sure it works. May as well use that command to set the | |
1057 | * proper timeouts for the driver. | |
1058 | */ | |
1059 | if (tpm_get_timeouts(chip)) { | |
1060 | dev_err(dev, "Could not get TPM timeouts and durations\n"); | |
1061 | rc = -ENODEV; | |
9550f210 | 1062 | goto out_err; |
d1d253cf JG |
1063 | } |
1064 | ||
41a5e1cf CR |
1065 | if (irq) { |
1066 | tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED, | |
1067 | irq); | |
b160c94b | 1068 | if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) { |
41a5e1cf CR |
1069 | dev_err(&chip->dev, FW_BUG |
1070 | "TPM interrupt not working, polling instead\n"); | |
b160c94b JS |
1071 | |
1072 | disable_interrupts(chip); | |
1073 | } | |
41a5e1cf CR |
1074 | } else { |
1075 | tpm_tis_probe_irq(chip, intmask); | |
1076 | } | |
1077 | } | |
1078 | ||
c382babc | 1079 | rc = tpm_chip_register(chip); |
b3e958ce | 1080 | if (rc) |
9550f210 | 1081 | goto out_err; |
21df4a8b | 1082 | |
9550f210 JS |
1083 | if (chip->ops->clk_enable != NULL) |
1084 | chip->ops->clk_enable(chip, false); | |
21df4a8b | 1085 | |
9550f210 JS |
1086 | return 0; |
1087 | out_err: | |
b3e958ce AS |
1088 | if ((chip->ops != NULL) && (chip->ops->clk_enable != NULL)) |
1089 | chip->ops->clk_enable(chip, false); | |
1090 | ||
41a5e1cf | 1091 | tpm_tis_remove(chip); |
c382babc | 1092 | |
41a5e1cf CR |
1093 | return rc; |
1094 | } | |
1095 | EXPORT_SYMBOL_GPL(tpm_tis_core_init); | |
1096 | ||
1097 | #ifdef CONFIG_PM_SLEEP | |
1098 | static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) | |
1099 | { | |
1100 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); | |
1101 | u32 intmask; | |
1102 | int rc; | |
1103 | ||
b3e958ce AS |
1104 | if (chip->ops->clk_enable != NULL) |
1105 | chip->ops->clk_enable(chip, true); | |
1106 | ||
41a5e1cf CR |
1107 | /* reenable interrupts that device may have lost or |
1108 | * BIOS/firmware may have disabled | |
1109 | */ | |
1110 | rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), priv->irq); | |
1111 | if (rc < 0) | |
b3e958ce | 1112 | goto out; |
41a5e1cf CR |
1113 | |
1114 | rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask); | |
1115 | if (rc < 0) | |
b3e958ce | 1116 | goto out; |
41a5e1cf CR |
1117 | |
1118 | intmask |= TPM_INTF_CMD_READY_INT | |
1119 | | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT | |
1120 | | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE; | |
1121 | ||
1122 | tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); | |
b3e958ce AS |
1123 | |
1124 | out: | |
1125 | if (chip->ops->clk_enable != NULL) | |
1126 | chip->ops->clk_enable(chip, false); | |
1127 | ||
1128 | return; | |
41a5e1cf CR |
1129 | } |
1130 | ||
1131 | int tpm_tis_resume(struct device *dev) | |
1132 | { | |
1133 | struct tpm_chip *chip = dev_get_drvdata(dev); | |
1134 | int ret; | |
1135 | ||
1136 | if (chip->flags & TPM_CHIP_FLAG_IRQ) | |
1137 | tpm_tis_reenable_interrupts(chip); | |
1138 | ||
1139 | ret = tpm_pm_resume(dev); | |
1140 | if (ret) | |
1141 | return ret; | |
1142 | ||
1143 | /* TPM 1.2 requires self-test on resume. This function actually returns | |
1144 | * an error code but for unknown reason it isn't handled. | |
1145 | */ | |
1146 | if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) | |
d4a31756 | 1147 | tpm1_do_selftest(chip); |
41a5e1cf CR |
1148 | |
1149 | return 0; | |
1150 | } | |
1151 | EXPORT_SYMBOL_GPL(tpm_tis_resume); | |
1152 | #endif | |
1153 | ||
1154 | MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); | |
1155 | MODULE_DESCRIPTION("TPM Driver"); | |
1156 | MODULE_VERSION("2.0"); | |
1157 | MODULE_LICENSE("GPL"); |