.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2005, 2006 IBM Corporation |
---|
3 | 4 | * Copyright (C) 2014, 2015 Intel Corporation |
---|
.. | .. |
---|
13 | 14 | * |
---|
14 | 15 | * This device driver implements the TPM interface as defined in |
---|
15 | 16 | * the TCG TPM Interface Spec version 1.2, revision 1.0. |
---|
16 | | - * |
---|
17 | | - * This program is free software; you can redistribute it and/or |
---|
18 | | - * modify it under the terms of the GNU General Public License as |
---|
19 | | - * published by the Free Software Foundation, version 2 of the |
---|
20 | | - * License. |
---|
21 | 17 | */ |
---|
22 | 18 | #include <linux/init.h> |
---|
23 | 19 | #include <linux/module.h> |
---|
.. | .. |
---|
52 | 48 | unsigned long timeout, wait_queue_head_t *queue, |
---|
53 | 49 | bool check_cancel) |
---|
54 | 50 | { |
---|
| 51 | + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
---|
55 | 52 | unsigned long stop; |
---|
56 | 53 | long rc; |
---|
57 | 54 | u8 status; |
---|
.. | .. |
---|
84 | 81 | } |
---|
85 | 82 | } else { |
---|
86 | 83 | do { |
---|
87 | | - usleep_range(TPM_TIMEOUT_USECS_MIN, |
---|
88 | | - TPM_TIMEOUT_USECS_MAX); |
---|
| 84 | + usleep_range(priv->timeout_min, |
---|
| 85 | + priv->timeout_max); |
---|
89 | 86 | status = chip->ops->status(chip); |
---|
90 | 87 | if ((status & mask) == mask) |
---|
91 | 88 | return 0; |
---|
.. | .. |
---|
139 | 136 | return false; |
---|
140 | 137 | } |
---|
141 | 138 | |
---|
142 | | -static int release_locality(struct tpm_chip *chip, int l) |
---|
| 139 | +static int __tpm_tis_relinquish_locality(struct tpm_tis_data *priv, int l) |
---|
143 | 140 | { |
---|
144 | | - struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
---|
145 | | - |
---|
146 | 141 | tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY); |
---|
147 | 142 | |
---|
148 | 143 | return 0; |
---|
149 | 144 | } |
---|
150 | 145 | |
---|
151 | | -static int request_locality(struct tpm_chip *chip, int l) |
---|
| 146 | +static int tpm_tis_relinquish_locality(struct tpm_chip *chip, int l) |
---|
| 147 | +{ |
---|
| 148 | + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
---|
| 149 | + |
---|
| 150 | + mutex_lock(&priv->locality_count_mutex); |
---|
| 151 | + priv->locality_count--; |
---|
| 152 | + if (priv->locality_count == 0) |
---|
| 153 | + __tpm_tis_relinquish_locality(priv, l); |
---|
| 154 | + mutex_unlock(&priv->locality_count_mutex); |
---|
| 155 | + |
---|
| 156 | + return 0; |
---|
| 157 | +} |
---|
| 158 | + |
---|
| 159 | +static int __tpm_tis_request_locality(struct tpm_chip *chip, int l) |
---|
152 | 160 | { |
---|
153 | 161 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
---|
154 | 162 | unsigned long stop, timeout; |
---|
.. | .. |
---|
189 | 197 | return -1; |
---|
190 | 198 | } |
---|
191 | 199 | |
---|
| 200 | +static int tpm_tis_request_locality(struct tpm_chip *chip, int l) |
---|
| 201 | +{ |
---|
| 202 | + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
---|
| 203 | + int ret = 0; |
---|
| 204 | + |
---|
| 205 | + mutex_lock(&priv->locality_count_mutex); |
---|
| 206 | + if (priv->locality_count == 0) |
---|
| 207 | + ret = __tpm_tis_request_locality(chip, l); |
---|
| 208 | + if (!ret) |
---|
| 209 | + priv->locality_count++; |
---|
| 210 | + mutex_unlock(&priv->locality_count_mutex); |
---|
| 211 | + return ret; |
---|
| 212 | +} |
---|
| 213 | + |
---|
192 | 214 | static u8 tpm_tis_status(struct tpm_chip *chip) |
---|
193 | 215 | { |
---|
194 | 216 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
---|
.. | .. |
---|
198 | 220 | rc = tpm_tis_read8(priv, TPM_STS(priv->locality), &status); |
---|
199 | 221 | if (rc < 0) |
---|
200 | 222 | return 0; |
---|
| 223 | + |
---|
| 224 | + if (unlikely((status & TPM_STS_READ_ZERO) != 0)) { |
---|
| 225 | + if (!test_and_set_bit(TPM_TIS_INVALID_STATUS, &priv->flags)) { |
---|
| 226 | + /* |
---|
| 227 | + * If this trips, the chances are the read is |
---|
| 228 | + * returning 0xff because the locality hasn't been |
---|
| 229 | + * acquired. Usually because tpm_try_get_ops() hasn't |
---|
| 230 | + * been called before doing a TPM operation. |
---|
| 231 | + */ |
---|
| 232 | + dev_err(&chip->dev, "invalid TPM_STS.x 0x%02x, dumping stack for forensics\n", |
---|
| 233 | + status); |
---|
| 234 | + |
---|
| 235 | + /* |
---|
| 236 | + * Dump stack for forensics, as invalid TPM_STS.x could be |
---|
| 237 | + * potentially triggered by impaired tpm_try_get_ops() or |
---|
| 238 | + * tpm_find_get_ops(). |
---|
| 239 | + */ |
---|
| 240 | + dump_stack(); |
---|
| 241 | + } |
---|
| 242 | + |
---|
| 243 | + return 0; |
---|
| 244 | + } |
---|
201 | 245 | |
---|
202 | 246 | return status; |
---|
203 | 247 | } |
---|
.. | .. |
---|
270 | 314 | int size = 0; |
---|
271 | 315 | int status; |
---|
272 | 316 | u32 expected; |
---|
| 317 | + int rc; |
---|
273 | 318 | |
---|
274 | 319 | if (count < TPM_HEADER_SIZE) { |
---|
275 | 320 | size = -EIO; |
---|
.. | .. |
---|
289 | 334 | goto out; |
---|
290 | 335 | } |
---|
291 | 336 | |
---|
292 | | - size += recv_data(chip, &buf[TPM_HEADER_SIZE], |
---|
293 | | - expected - TPM_HEADER_SIZE); |
---|
| 337 | + rc = recv_data(chip, &buf[TPM_HEADER_SIZE], |
---|
| 338 | + expected - TPM_HEADER_SIZE); |
---|
| 339 | + if (rc < 0) { |
---|
| 340 | + size = rc; |
---|
| 341 | + goto out; |
---|
| 342 | + } |
---|
| 343 | + size += rc; |
---|
294 | 344 | if (size < expected) { |
---|
295 | 345 | dev_err(&chip->dev, "Unable to read remainder of result\n"); |
---|
296 | 346 | size = -ETIME; |
---|
.. | .. |
---|
419 | 469 | int rc; |
---|
420 | 470 | u32 ordinal; |
---|
421 | 471 | unsigned long dur; |
---|
| 472 | + unsigned int try; |
---|
422 | 473 | |
---|
423 | | - rc = tpm_tis_send_data(chip, buf, len); |
---|
424 | | - if (rc < 0) |
---|
425 | | - return rc; |
---|
| 474 | + for (try = 0; try < TPM_RETRY; try++) { |
---|
| 475 | + rc = tpm_tis_send_data(chip, buf, len); |
---|
| 476 | + if (rc >= 0) |
---|
| 477 | + /* Data transfer done successfully */ |
---|
| 478 | + break; |
---|
| 479 | + else if (rc != -EIO) |
---|
| 480 | + /* Data transfer failed, not recoverable */ |
---|
| 481 | + return rc; |
---|
| 482 | + } |
---|
426 | 483 | |
---|
427 | 484 | /* go and do it */ |
---|
428 | 485 | rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO); |
---|
.. | .. |
---|
432 | 489 | if (chip->flags & TPM_CHIP_FLAG_IRQ) { |
---|
433 | 490 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); |
---|
434 | 491 | |
---|
435 | | - if (chip->flags & TPM_CHIP_FLAG_TPM2) |
---|
436 | | - dur = tpm2_calc_ordinal_duration(chip, ordinal); |
---|
437 | | - else |
---|
438 | | - dur = tpm_calc_ordinal_duration(chip, ordinal); |
---|
439 | | - |
---|
| 492 | + dur = tpm_calc_ordinal_duration(chip, ordinal); |
---|
440 | 493 | if (wait_for_tpm_stat |
---|
441 | 494 | (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur, |
---|
442 | 495 | &priv->read_queue, false) < 0) { |
---|
.. | .. |
---|
473 | 526 | return rc; |
---|
474 | 527 | } |
---|
475 | 528 | |
---|
| 529 | +struct tis_vendor_durations_override { |
---|
| 530 | + u32 did_vid; |
---|
| 531 | + struct tpm1_version version; |
---|
| 532 | + unsigned long durations[3]; |
---|
| 533 | +}; |
---|
| 534 | + |
---|
| 535 | +static const struct tis_vendor_durations_override vendor_dur_overrides[] = { |
---|
| 536 | + /* STMicroelectronics 0x104a */ |
---|
| 537 | + { 0x0000104a, |
---|
| 538 | + { 1, 2, 8, 28 }, |
---|
| 539 | + { (2 * 60 * HZ), (2 * 60 * HZ), (2 * 60 * HZ) } }, |
---|
| 540 | +}; |
---|
| 541 | + |
---|
| 542 | +static void tpm_tis_update_durations(struct tpm_chip *chip, |
---|
| 543 | + unsigned long *duration_cap) |
---|
| 544 | +{ |
---|
| 545 | + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
---|
| 546 | + struct tpm1_version *version; |
---|
| 547 | + u32 did_vid; |
---|
| 548 | + int i, rc; |
---|
| 549 | + cap_t cap; |
---|
| 550 | + |
---|
| 551 | + chip->duration_adjusted = false; |
---|
| 552 | + |
---|
| 553 | + if (chip->ops->clk_enable != NULL) |
---|
| 554 | + chip->ops->clk_enable(chip, true); |
---|
| 555 | + |
---|
| 556 | + rc = tpm_tis_read32(priv, TPM_DID_VID(0), &did_vid); |
---|
| 557 | + if (rc < 0) { |
---|
| 558 | + dev_warn(&chip->dev, "%s: failed to read did_vid. %d\n", |
---|
| 559 | + __func__, rc); |
---|
| 560 | + goto out; |
---|
| 561 | + } |
---|
| 562 | + |
---|
| 563 | + /* Try to get a TPM version 1.2 or 1.1 TPM_CAP_VERSION_INFO */ |
---|
| 564 | + rc = tpm1_getcap(chip, TPM_CAP_VERSION_1_2, &cap, |
---|
| 565 | + "attempting to determine the 1.2 version", |
---|
| 566 | + sizeof(cap.version2)); |
---|
| 567 | + if (!rc) { |
---|
| 568 | + version = &cap.version2.version; |
---|
| 569 | + } else { |
---|
| 570 | + rc = tpm1_getcap(chip, TPM_CAP_VERSION_1_1, &cap, |
---|
| 571 | + "attempting to determine the 1.1 version", |
---|
| 572 | + sizeof(cap.version1)); |
---|
| 573 | + |
---|
| 574 | + if (rc) |
---|
| 575 | + goto out; |
---|
| 576 | + |
---|
| 577 | + version = &cap.version1; |
---|
| 578 | + } |
---|
| 579 | + |
---|
| 580 | + for (i = 0; i != ARRAY_SIZE(vendor_dur_overrides); i++) { |
---|
| 581 | + if (vendor_dur_overrides[i].did_vid != did_vid) |
---|
| 582 | + continue; |
---|
| 583 | + |
---|
| 584 | + if ((version->major == |
---|
| 585 | + vendor_dur_overrides[i].version.major) && |
---|
| 586 | + (version->minor == |
---|
| 587 | + vendor_dur_overrides[i].version.minor) && |
---|
| 588 | + (version->rev_major == |
---|
| 589 | + vendor_dur_overrides[i].version.rev_major) && |
---|
| 590 | + (version->rev_minor == |
---|
| 591 | + vendor_dur_overrides[i].version.rev_minor)) { |
---|
| 592 | + |
---|
| 593 | + memcpy(duration_cap, |
---|
| 594 | + vendor_dur_overrides[i].durations, |
---|
| 595 | + sizeof(vendor_dur_overrides[i].durations)); |
---|
| 596 | + |
---|
| 597 | + chip->duration_adjusted = true; |
---|
| 598 | + goto out; |
---|
| 599 | + } |
---|
| 600 | + } |
---|
| 601 | + |
---|
| 602 | +out: |
---|
| 603 | + if (chip->ops->clk_enable != NULL) |
---|
| 604 | + chip->ops->clk_enable(chip, false); |
---|
| 605 | +} |
---|
| 606 | + |
---|
476 | 607 | struct tis_vendor_timeout_override { |
---|
477 | 608 | u32 did_vid; |
---|
478 | 609 | unsigned long timeout_us[4]; |
---|
.. | .. |
---|
484 | 615 | (TIS_SHORT_TIMEOUT*1000), (TIS_SHORT_TIMEOUT*1000) } }, |
---|
485 | 616 | }; |
---|
486 | 617 | |
---|
487 | | -static bool tpm_tis_update_timeouts(struct tpm_chip *chip, |
---|
| 618 | +static void tpm_tis_update_timeouts(struct tpm_chip *chip, |
---|
488 | 619 | unsigned long *timeout_cap) |
---|
489 | 620 | { |
---|
490 | 621 | struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); |
---|
491 | 622 | int i, rc; |
---|
492 | 623 | u32 did_vid; |
---|
493 | 624 | |
---|
| 625 | + chip->timeout_adjusted = false; |
---|
| 626 | + |
---|
494 | 627 | if (chip->ops->clk_enable != NULL) |
---|
495 | 628 | chip->ops->clk_enable(chip, true); |
---|
496 | 629 | |
---|
497 | 630 | rc = tpm_tis_read32(priv, TPM_DID_VID(0), &did_vid); |
---|
498 | | - if (rc < 0) |
---|
| 631 | + if (rc < 0) { |
---|
| 632 | + dev_warn(&chip->dev, "%s: failed to read did_vid: %d\n", |
---|
| 633 | + __func__, rc); |
---|
499 | 634 | goto out; |
---|
| 635 | + } |
---|
500 | 636 | |
---|
501 | 637 | for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) { |
---|
502 | 638 | if (vendor_timeout_overrides[i].did_vid != did_vid) |
---|
503 | 639 | continue; |
---|
504 | 640 | memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us, |
---|
505 | 641 | sizeof(vendor_timeout_overrides[i].timeout_us)); |
---|
506 | | - rc = true; |
---|
| 642 | + chip->timeout_adjusted = true; |
---|
507 | 643 | } |
---|
508 | | - |
---|
509 | | - rc = false; |
---|
510 | 644 | |
---|
511 | 645 | out: |
---|
512 | 646 | if (chip->ops->clk_enable != NULL) |
---|
513 | 647 | chip->ops->clk_enable(chip, false); |
---|
514 | 648 | |
---|
515 | | - return rc; |
---|
| 649 | + return; |
---|
516 | 650 | } |
---|
517 | 651 | |
---|
518 | 652 | /* |
---|
.. | .. |
---|
542 | 676 | if (vendor != TPM_VID_INTEL) |
---|
543 | 677 | return 0; |
---|
544 | 678 | |
---|
545 | | - if (request_locality(chip, 0) != 0) |
---|
| 679 | + if (tpm_tis_request_locality(chip, 0) != 0) |
---|
546 | 680 | return -EBUSY; |
---|
547 | 681 | |
---|
548 | 682 | rc = tpm_tis_send_data(chip, cmd_getticks, len); |
---|
.. | .. |
---|
563 | 697 | |
---|
564 | 698 | out: |
---|
565 | 699 | tpm_tis_ready(chip); |
---|
566 | | - release_locality(chip, priv->locality); |
---|
| 700 | + tpm_tis_relinquish_locality(chip, priv->locality); |
---|
567 | 701 | |
---|
568 | 702 | return rc; |
---|
569 | 703 | } |
---|
.. | .. |
---|
610 | 744 | wake_up_interruptible(&priv->int_queue); |
---|
611 | 745 | |
---|
612 | 746 | /* Clear interrupts handled with TPM_EOI */ |
---|
| 747 | + tpm_tis_request_locality(chip, 0); |
---|
613 | 748 | rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), interrupt); |
---|
| 749 | + tpm_tis_relinquish_locality(chip, 0); |
---|
614 | 750 | if (rc < 0) |
---|
615 | 751 | return IRQ_NONE; |
---|
616 | 752 | |
---|
.. | .. |
---|
618 | 754 | return IRQ_HANDLED; |
---|
619 | 755 | } |
---|
620 | 756 | |
---|
621 | | -static int tpm_tis_gen_interrupt(struct tpm_chip *chip) |
---|
| 757 | +static void tpm_tis_gen_interrupt(struct tpm_chip *chip) |
---|
622 | 758 | { |
---|
623 | 759 | const char *desc = "attempting to generate an interrupt"; |
---|
624 | 760 | u32 cap2; |
---|
625 | 761 | cap_t cap; |
---|
| 762 | + int ret; |
---|
626 | 763 | |
---|
627 | 764 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
---|
628 | | - return tpm2_get_tpm_pt(chip, 0x100, &cap2, desc); |
---|
| 765 | + ret = tpm2_get_tpm_pt(chip, 0x100, &cap2, desc); |
---|
629 | 766 | else |
---|
630 | | - return tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, |
---|
631 | | - 0); |
---|
| 767 | + ret = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, 0); |
---|
632 | 768 | } |
---|
633 | 769 | |
---|
634 | 770 | /* Register the IRQ and issue a command that will cause an interrupt. If an |
---|
.. | .. |
---|
643 | 779 | int rc; |
---|
644 | 780 | u32 int_status; |
---|
645 | 781 | |
---|
646 | | - if (devm_request_irq(chip->dev.parent, irq, tis_int_handler, flags, |
---|
647 | | - dev_name(&chip->dev), chip) != 0) { |
---|
| 782 | + |
---|
| 783 | + rc = devm_request_threaded_irq(chip->dev.parent, irq, NULL, |
---|
| 784 | + tis_int_handler, IRQF_ONESHOT | flags, |
---|
| 785 | + dev_name(&chip->dev), chip); |
---|
| 786 | + if (rc) { |
---|
648 | 787 | dev_info(&chip->dev, "Unable to request irq: %d for probe\n", |
---|
649 | 788 | irq); |
---|
650 | 789 | return -1; |
---|
651 | 790 | } |
---|
652 | 791 | priv->irq = irq; |
---|
653 | 792 | |
---|
654 | | - rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality), |
---|
655 | | - &original_int_vec); |
---|
| 793 | + rc = tpm_tis_request_locality(chip, 0); |
---|
656 | 794 | if (rc < 0) |
---|
657 | 795 | return rc; |
---|
| 796 | + |
---|
| 797 | + rc = tpm_tis_read8(priv, TPM_INT_VECTOR(priv->locality), |
---|
| 798 | + &original_int_vec); |
---|
| 799 | + if (rc < 0) { |
---|
| 800 | + tpm_tis_relinquish_locality(chip, priv->locality); |
---|
| 801 | + return rc; |
---|
| 802 | + } |
---|
658 | 803 | |
---|
659 | 804 | rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), irq); |
---|
660 | 805 | if (rc < 0) |
---|
661 | | - return rc; |
---|
| 806 | + goto restore_irqs; |
---|
662 | 807 | |
---|
663 | 808 | rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &int_status); |
---|
664 | 809 | if (rc < 0) |
---|
665 | | - return rc; |
---|
| 810 | + goto restore_irqs; |
---|
666 | 811 | |
---|
667 | 812 | /* Clear all existing */ |
---|
668 | 813 | rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), int_status); |
---|
669 | 814 | if (rc < 0) |
---|
670 | | - return rc; |
---|
671 | | - |
---|
| 815 | + goto restore_irqs; |
---|
672 | 816 | /* Turn on */ |
---|
673 | 817 | rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), |
---|
674 | 818 | intmask | TPM_GLOBAL_INT_ENABLE); |
---|
675 | 819 | if (rc < 0) |
---|
676 | | - return rc; |
---|
| 820 | + goto restore_irqs; |
---|
677 | 821 | |
---|
678 | 822 | priv->irq_tested = false; |
---|
679 | 823 | |
---|
680 | 824 | /* Generate an interrupt by having the core call through to |
---|
681 | 825 | * tpm_tis_send |
---|
682 | 826 | */ |
---|
683 | | - rc = tpm_tis_gen_interrupt(chip); |
---|
684 | | - if (rc < 0) |
---|
685 | | - return rc; |
---|
| 827 | + tpm_tis_gen_interrupt(chip); |
---|
686 | 828 | |
---|
| 829 | +restore_irqs: |
---|
687 | 830 | /* tpm_tis_send will either confirm the interrupt is working or it |
---|
688 | 831 | * will call disable_irq which undoes all of the above. |
---|
689 | 832 | */ |
---|
690 | 833 | if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) { |
---|
691 | | - rc = tpm_tis_write8(priv, original_int_vec, |
---|
692 | | - TPM_INT_VECTOR(priv->locality)); |
---|
693 | | - if (rc < 0) |
---|
694 | | - return rc; |
---|
695 | | - |
---|
696 | | - return 1; |
---|
| 834 | + tpm_tis_write8(priv, original_int_vec, |
---|
| 835 | + TPM_INT_VECTOR(priv->locality)); |
---|
| 836 | + rc = -1; |
---|
697 | 837 | } |
---|
698 | 838 | |
---|
699 | | - return 0; |
---|
| 839 | + tpm_tis_relinquish_locality(chip, priv->locality); |
---|
| 840 | + |
---|
| 841 | + return rc; |
---|
700 | 842 | } |
---|
701 | 843 | |
---|
702 | 844 | /* Try to find the IRQ the TPM is using. This is for legacy x86 systems that |
---|
.. | .. |
---|
806 | 948 | .send = tpm_tis_send, |
---|
807 | 949 | .cancel = tpm_tis_ready, |
---|
808 | 950 | .update_timeouts = tpm_tis_update_timeouts, |
---|
| 951 | + .update_durations = tpm_tis_update_durations, |
---|
809 | 952 | .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
---|
810 | 953 | .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
---|
811 | 954 | .req_canceled = tpm_tis_req_canceled, |
---|
812 | | - .request_locality = request_locality, |
---|
813 | | - .relinquish_locality = release_locality, |
---|
| 955 | + .request_locality = tpm_tis_request_locality, |
---|
| 956 | + .relinquish_locality = tpm_tis_relinquish_locality, |
---|
814 | 957 | .clk_enable = tpm_tis_clkrun_enable, |
---|
815 | 958 | }; |
---|
816 | 959 | |
---|
.. | .. |
---|
841 | 984 | chip->timeout_b = msecs_to_jiffies(TIS_TIMEOUT_B_MAX); |
---|
842 | 985 | chip->timeout_c = msecs_to_jiffies(TIS_TIMEOUT_C_MAX); |
---|
843 | 986 | chip->timeout_d = msecs_to_jiffies(TIS_TIMEOUT_D_MAX); |
---|
| 987 | + priv->timeout_min = TPM_TIMEOUT_USECS_MIN; |
---|
| 988 | + priv->timeout_max = TPM_TIMEOUT_USECS_MAX; |
---|
844 | 989 | priv->phy_ops = phy_ops; |
---|
| 990 | + priv->locality_count = 0; |
---|
| 991 | + mutex_init(&priv->locality_count_mutex); |
---|
| 992 | + |
---|
845 | 993 | dev_set_drvdata(&chip->dev, priv); |
---|
| 994 | + |
---|
| 995 | + rc = tpm_tis_read32(priv, TPM_DID_VID(0), &vendor); |
---|
| 996 | + if (rc < 0) |
---|
| 997 | + return rc; |
---|
| 998 | + |
---|
| 999 | + priv->manufacturer_id = vendor; |
---|
| 1000 | + |
---|
| 1001 | + if (priv->manufacturer_id == TPM_VID_ATML && |
---|
| 1002 | + !(chip->flags & TPM_CHIP_FLAG_TPM2)) { |
---|
| 1003 | + priv->timeout_min = TIS_TIMEOUT_MIN_ATML; |
---|
| 1004 | + priv->timeout_max = TIS_TIMEOUT_MAX_ATML; |
---|
| 1005 | + } |
---|
846 | 1006 | |
---|
847 | 1007 | if (is_bsw()) { |
---|
848 | 1008 | priv->ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR, |
---|
.. | .. |
---|
875 | 1035 | TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT; |
---|
876 | 1036 | intmask &= ~TPM_GLOBAL_INT_ENABLE; |
---|
877 | 1037 | |
---|
878 | | - rc = request_locality(chip, 0); |
---|
| 1038 | + rc = tpm_tis_request_locality(chip, 0); |
---|
879 | 1039 | if (rc < 0) { |
---|
880 | 1040 | rc = -ENODEV; |
---|
881 | 1041 | goto out_err; |
---|
882 | 1042 | } |
---|
883 | 1043 | |
---|
884 | 1044 | tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); |
---|
885 | | - release_locality(chip, 0); |
---|
| 1045 | + tpm_tis_relinquish_locality(chip, 0); |
---|
886 | 1046 | |
---|
887 | | - rc = tpm2_probe(chip); |
---|
| 1047 | + rc = tpm_chip_start(chip); |
---|
888 | 1048 | if (rc) |
---|
889 | 1049 | goto out_err; |
---|
890 | | - |
---|
891 | | - rc = tpm_tis_read32(priv, TPM_DID_VID(0), &vendor); |
---|
892 | | - if (rc < 0) |
---|
| 1050 | + rc = tpm2_probe(chip); |
---|
| 1051 | + tpm_chip_stop(chip); |
---|
| 1052 | + if (rc) |
---|
893 | 1053 | goto out_err; |
---|
894 | | - |
---|
895 | | - priv->manufacturer_id = vendor; |
---|
896 | 1054 | |
---|
897 | 1055 | rc = tpm_tis_read8(priv, TPM_RID(0), &rid); |
---|
898 | 1056 | if (rc < 0) |
---|
.. | .. |
---|
938 | 1096 | init_waitqueue_head(&priv->read_queue); |
---|
939 | 1097 | init_waitqueue_head(&priv->int_queue); |
---|
940 | 1098 | if (irq != -1) { |
---|
941 | | - /* Before doing irq testing issue a command to the TPM in polling mode |
---|
| 1099 | + /* |
---|
| 1100 | + * Before doing irq testing issue a command to the TPM in polling mode |
---|
942 | 1101 | * to make sure it works. May as well use that command to set the |
---|
943 | 1102 | * proper timeouts for the driver. |
---|
944 | 1103 | */ |
---|
945 | | - if (tpm_get_timeouts(chip)) { |
---|
| 1104 | + |
---|
| 1105 | + rc = tpm_tis_request_locality(chip, 0); |
---|
| 1106 | + if (rc < 0) |
---|
| 1107 | + goto out_err; |
---|
| 1108 | + |
---|
| 1109 | + rc = tpm_get_timeouts(chip); |
---|
| 1110 | + |
---|
| 1111 | + tpm_tis_relinquish_locality(chip, 0); |
---|
| 1112 | + |
---|
| 1113 | + if (rc) { |
---|
946 | 1114 | dev_err(dev, "Could not get TPM timeouts and durations\n"); |
---|
947 | 1115 | rc = -ENODEV; |
---|
948 | 1116 | goto out_err; |
---|
949 | 1117 | } |
---|
950 | 1118 | |
---|
951 | | - if (irq) { |
---|
| 1119 | + if (irq) |
---|
952 | 1120 | tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED, |
---|
953 | 1121 | irq); |
---|
954 | | - if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) { |
---|
955 | | - dev_err(&chip->dev, FW_BUG |
---|
| 1122 | + else |
---|
| 1123 | + tpm_tis_probe_irq(chip, intmask); |
---|
| 1124 | + |
---|
| 1125 | + if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) { |
---|
| 1126 | + dev_err(&chip->dev, FW_BUG |
---|
956 | 1127 | "TPM interrupt not working, polling instead\n"); |
---|
957 | 1128 | |
---|
958 | | - disable_interrupts(chip); |
---|
959 | | - } |
---|
960 | | - } else { |
---|
961 | | - tpm_tis_probe_irq(chip, intmask); |
---|
| 1129 | + rc = tpm_tis_request_locality(chip, 0); |
---|
| 1130 | + if (rc < 0) |
---|
| 1131 | + goto out_err; |
---|
| 1132 | + disable_interrupts(chip); |
---|
| 1133 | + tpm_tis_relinquish_locality(chip, 0); |
---|
962 | 1134 | } |
---|
963 | 1135 | } |
---|
964 | 1136 | |
---|
.. | .. |
---|
1019 | 1191 | struct tpm_chip *chip = dev_get_drvdata(dev); |
---|
1020 | 1192 | int ret; |
---|
1021 | 1193 | |
---|
| 1194 | + ret = tpm_tis_request_locality(chip, 0); |
---|
| 1195 | + if (ret < 0) |
---|
| 1196 | + return ret; |
---|
| 1197 | + |
---|
1022 | 1198 | if (chip->flags & TPM_CHIP_FLAG_IRQ) |
---|
1023 | 1199 | tpm_tis_reenable_interrupts(chip); |
---|
1024 | 1200 | |
---|
1025 | 1201 | ret = tpm_pm_resume(dev); |
---|
1026 | 1202 | if (ret) |
---|
1027 | | - return ret; |
---|
| 1203 | + goto out; |
---|
1028 | 1204 | |
---|
1029 | | - /* TPM 1.2 requires self-test on resume. This function actually returns |
---|
| 1205 | + /* |
---|
| 1206 | + * TPM 1.2 requires self-test on resume. This function actually returns |
---|
1030 | 1207 | * an error code but for unknown reason it isn't handled. |
---|
1031 | 1208 | */ |
---|
1032 | 1209 | if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) |
---|
1033 | | - tpm_do_selftest(chip); |
---|
| 1210 | + tpm1_do_selftest(chip); |
---|
| 1211 | +out: |
---|
| 1212 | + tpm_tis_relinquish_locality(chip, 0); |
---|
1034 | 1213 | |
---|
1035 | | - return 0; |
---|
| 1214 | + return ret; |
---|
1036 | 1215 | } |
---|
1037 | 1216 | EXPORT_SYMBOL_GPL(tpm_tis_resume); |
---|
1038 | 1217 | #endif |
---|