Commit Graph

14 Commits

Author SHA1 Message Date
Vadim Bendebury
3919001a39 tpm: provide means of shutting down comms layer while in reset
Currently the Cr50 code resets TPM communications layer at a certain
point during TPM reset process.

It turns out that this is not sufficient - the comms layer keeps
receiving and trying to invoke TPM layer, which does not mesh well
with TPM reset.

Let's provide two callbacks for each comms layer - to shut it down and
to bring it back up. We shut down the comms when starting TPM reset
and bring them back up when reset is completed.

BRANCH=cr50
BUG=b:68012381
TEST=ran AP firmware test suite on both SPI and I2C based devices.

Change-Id: I7caf4a09b9a5c6e5fc6bfe60eae1c0d64ab24904
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/754502
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
2017-11-07 17:52:15 -08:00
Vadim Bendebury
430d55879d g: add 'recover hosed slave' i2cs capability
A common failure condition on the i2c bus is when the master
unexpectedly stops clocking the bus while the slave is driving the SDA
line low. In this case the master is not able to issue Stop or Start
sequences, which makes the bus unusable.

Good slave controllers are able to detect this condition and recover
from it by removing the pull down from the SDA line. This patch adds
this capability to the g chip i2c slave controller.

A new timer function is created which samples the SDA line twice a
second. If it detects that SDA is low in two consecutive invocations
and the number of i2cs read interrupts has not advanced, it decides
that the "hosed slave" condition is happening and reinitializes the
i2c driver, which removes the hold from the SDA line.

Even though the state of the SDA line is supposed to be accessible
through the I2CS_READVAL register, it in fact is not, reads always
return zero in the SDA bit. To work around this a GPIO (port 0, bit
14) is being allocated to allow to monitor the state of the line, it
is multiplexed to the same pin the SDA line uses.

When the AP is in low power modes the SDA line is held low, this state
should not trigger i2c reinitializations.

CQ-DEPEND=CL:616300
BRANCH=none
BUG=b:35648537
TEST=connected H1 on the test board to an I2c master capable of
     stopping clocking mid byte. Observed that the existing code would
     just sit in the "hosed" state indefinitely. The code with the fix
     recovers from the condition (drives the SDA line high) 500ms to
     1s after the failure condition is created.

Change-Id: Iafc7433bbae9e49975a72ef032a923274f8aab3b
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/614391
Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
2017-08-17 20:41:57 -07:00
Scott
4aa861680f Cr50: i2cs: Added counter for write mismatch error
During TPM I2CS stress testing as described in chrome-os-partner:59191
there were instances of write mismatch errors. Previously, there was a
CPRINTF for this condition. The CPRINTF being in the i2cs ISR then
affects any subsequent i2cs activity and can create a cascade of
errors.

To avoid this issue, added a counter to track these instances and made
it to be retrieved similar to the fifo adjust counter.

BRANCH=none
BUG=chrome-os-partner:57338,chrome-os-partner:59191
TEST=manual
Ran the stress test as described in chrome-os-partner:59191 and found
that when the write mismatch occurred the counter ticked up by 2 where
before there would be numerous console log prints of the same error.

Change-Id: I2837d02037e2f47b5bd4b001d3394ad6eb4bd92c
Signed-off-by: Scott <scollyer@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/410032
Commit-Ready: Scott Collyer <scollyer@chromium.org>
Tested-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
2017-02-02 12:29:30 -08:00
Vadim Bendebury
9cc53cb892 cr50: keep board properties related code in board.c
There are plans to extend use of the LONG_LIFE_SCRATCH1 register for
other purposes than keeping board properties. Just as the board
properties, the new use is also very board specific. This patch moves
the board properties code from chip/g to board/cr50, where it belongs.

Instead of reading board properties bitmap and checking if various
bits are set, api functions are now provided to allow determining
various properties settings without actually looking at the properties
bitmap.

CQ-DEPEND=CL:*313057
BRANCH=none
BUG=chrome-os-partner:58961
TEST=verified that both Gru and Reef boot with the new image,
     additionally, on Reef confirmed that it is possible to
     communicate with the H1 over USB, and that plt_reset signal is
     handled properly.

Change-Id: Id0dd2dc16389f773a149fb01eee1ce7bb99c4547
Reviewed-on: https://chromium-review.googlesource.com/422081
Commit-Ready: Vadim Bendebury <vbendeb@chromium.org>
Tested-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-by: Scott Collyer <scollyer@chromium.org>
2016-12-20 21:56:41 -08:00
Scott
3405c79584 Cr50: I2CS TPM: Ensure HW read fifo is empty for register reads
This change is a safegaurd to ensure that TPM register data is always
placed in the correct location in the HW read I2CS fifo. It is only
checked for 1 or 4 byte regsiter reads. Because of the way in which a
TPM command is sent and the response is read, there are multiple reads
of the STS register prior to reading the TPM fifo register. Therefore
ensuring the fifo has zero depth when 1 or 4 byte regsiter reads,
improves the robustness of the design.

Added a counter to track the number of times the fifo is adjusted and
a new console command 'i2cs disp|rst' to display the count and reset
it to 0 if desired.

Removed section in code for TPM fifo register reads intended to handle
the case where there was a mismatch between how many bytes were copied
into the fifo and the number read by the host. Since the burstcount
field in the status register always contains a valid amount of data
that can be read by the host, there should not be cases where the
host reads less data than was copied from the TPM fifo register. In
the unexpected cases where the host may not drain all of the I2CS read
fifo data during a TPM register read, the I2CS fifo depth will be
corrected the next time that it reads either the access or STS
register which happens prior to the start of any TPM transaction.

BRANCH=none
BUG=chrome-os-partner:57338,chrome-os-partner:59191
TEST=manual
Booted Reef and verfied that TPM functionality is working.

Change-Id: I065a55e64bbcc0cb3357a2bd83447a05400b8899
Signed-off-by: Scott <scollyer@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/382689
Commit-Ready: Scott Collyer <scollyer@chromium.org>
Tested-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
2016-11-04 18:31:46 -07:00
Scott
450b944ca9 Cr50: i2cs: Re-enable sleep after every interrupt
Previously, sleep was being reenabled only after tpm fifo reads as
that would typcially be near the end of a host driven TPM
command. However, in the case the host reads or writes to the STS
register, then sleep would not be re-enabled. Moved the re-enable
point to at the end of every i2cs interrupt. Since sleep is delayed by
1 second prior to being reenabled then Cr50 will not go to sleep in
the middle of TPM command since the host is either writing or reading
STS at a much faster rate when a TPM command is being executed.

BRANCH=none
BUG=chrome-os-partner:40397
TEST=manual
Added a debug counter in idle.c and shortened sleep delays from 3
minutes to 5 seconds. Unplugged suzyq and verified that when
reconnected, the counter was incrementing to verify that Reef would
go to sleep. Also verified that TPM worked successfully and kernel
was launched.

Change-Id: I03ad33ed3591bbba24b5c56445c06d0e11368019
Signed-off-by: Scott <scollyer@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/401808
Commit-Ready: Scott Collyer <scollyer@chromium.org>
Tested-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
2016-10-26 01:45:29 -07:00
Vadim Bendebury
5a6bb19a88 tpm: reset communications channels when resetting TPM
TPM resets happen asynchronously, conceivably there is some interface
(i2cs or sps) activity under way when TPM is reset.

Sps driver provides a means of disconnecting the client of the driver,
while the i2cs driver does not. Come to think of it, there is no real
need to provide a special function to disconnect a client, this makes
API simpler and allows to add driver initialization to the client
registration function.

To make tpm_registers.c more flexible - allow to register a callback
for interface initialization, this way when TPM is reset, the
interface can be also re-initialized and is guaranteed to start from
scratch after reset.

BRANCH=none
BUG=chrome-os-partner:52366
TEST=both firmware_TPMExtend and firmware_TPMKernelVersion autotests
     pass

Change-Id: I212166a23f9cd512d8f75315377d1f5620aea070
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/388886
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
2016-09-26 22:16:45 -07:00
Scott
672ea89dba Cr50: I2CS TPM: Prevent sleep when I2CS is active
Similar to the TPM SPI interface, added code to disable sleep an I2CS
interrupt is received. Enabling sleep follwoing a 1 second delay when
the TPM fifo register has been read by the host. The I2CS TPM layer
doesn't know when a command has finished, but the one second delay is
more than enough delay since sleep will be disabled again when the
next I2CS interrupt is received.

BRANCH=none
BUG=chrome-os-partner:40397
TEST=manual
Tested without these changes first. Shortened sleep delay to 30
seconds, and disconnected suzyq. Waited 30 seconds then issued the
command on the AP console:

tpmc read 0x1007 0xa
[   59.796813] tpm tpm0: tpm_transmit: tpm_send: error -16
ERROR: write failure to TPM device: Device or resource busy

In addition, using logic analyzer verifed that there was activity on
SDA/SCL but no response from Cr50. With this CL in place, ran the
test and got the following:

tpmc read 0x1007 0xa
2 0 1 0 1 0 0 0 0 4f

With the logic analyzer I was able to confirm that there was no
activity from the host on the I2CS bus until the command was issued.

Change-Id: If07573ae8f72b983bca57979d53c22660b91b95e
Signed-off-by: Scott <scollyer@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/387910
Commit-Ready: Scott Collyer <scollyer@chromium.org>
Tested-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
2016-09-25 17:47:29 -07:00
Vadim Bendebury
d50b7699b5 g: generate AP_INT_L pulse after i2cs processing finished
The g i2c slave controller does not support clock stretching, so it is
necessary to flow control the AP by some other means. Luckily there is
an interrupt line which g can toggle and the AP can watch.

This patch adds generating a pulse on the AP interrupt line once g
finished processing the i2c transaction. In case of the read
transaction the pulse is generated after the data to read is put in
the i2cs transmit buffer.

BRANCH=none
BUG=chrome-os-partner:57338
TEST=with this patch and the AP firmware synchronizing on the
     interrupt pulse, the TPM initialization succeeds in coreboot and
     depthcharge.

Change-Id: I16c09b59b7d772624baa9d1f5258aaff26f91ff9
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/385256
Reviewed-by: Scott Collyer <scollyer@chromium.org>
2016-09-15 13:42:16 -07:00
Scott
017606c927 Cr50: I2CS TPM: Combine 1 and 4 byte register read block
In the initial design multi-byte registers were being converted to
network byte order and so there was reason to treat 1 byte and 4 byte
register reads differently. However, since the conversion to network
byte order is not being done, there is no reason to treat these cases
differently outside of the number of bytes to read.

BRANCH=none
BUG=chrome-os-partner:40397
TEST=manual
Reboot Reef and verify that TPM is working in coreboot
coreboot-coreboot-unknown.9999.fbbcb2d Thu Sep  8 19:41:15 UTC 2016
LPSS I2C bus 2 at 0xfe022000 (400 KHz)
tpm_vendor_probe: ValidSts bit set(1) in TPM_ACCESS register after 5 ms
I2C TPM 2:50 (chip type cr50 device-id 0x28)
setup_tpm():404: TPM: SetupTPM() succeeded
src/lib/tpm2_tlcl.c:179 index 0x1007 return code 0

Change-Id: If74c432136c02d334e0d58d16dc817d7773b0584
Signed-off-by: Scott <scollyer@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/382688
Commit-Ready: Scott Collyer <scollyer@chromium.org>
Tested-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
2016-09-12 12:53:59 -07:00
Scott
d5639272e2 Cr50: I2CS TPM: Added routine to write to HW fifo a word at a time
Reads of the TPM fifo by the Host are done in chunks of up to 63 bytes
at a time. The existing routine used to copy data read from the TPM
layer to the I2CS fifo operates one byte at a time. This method is
fine for single and four byte register reads. However, for larger
buffers the performace can be improved by aligning the the fifo write
pointer to be at a word boundary.

BRANCH=none
BUG=chrome-os-partner:40397
TEST=manual
Utilized test code on the host to initiate TPM fifo reads of various
lengths and added timing markers on the Cr50 to compare performance
between the existing byte at a time and the new full buffer write
funciton. Verifed that the fifo reads will still correct and compared
the time consumed copy TPM fifo data to the I2CS HW fifo.
This test processed 1910 bytes over 34 fifo reads.

Byte at a time method:
1910 bytes: 6375 uS: Avg Time = 3.233 uS per byte

Full buffer write:
1910 bytes: 3009 uS: Avg Time = 1.57 uS per byte

Change-Id: I3a47a350ab7af740a452fd115c33117b453b9611
Signed-off-by: Scott <scollyer@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/377663
Commit-Ready: Scott Collyer <scollyer@chromium.org>
Tested-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
2016-09-05 23:22:18 -07:00
Scott
7edd3827cf Cr50: I2CS TPM: Changes to support fifo and version registers read
This CL adds support for reading of TPM fifo registers. Since I2C does
not provide means to communicate how many bytes the host wants to read
there must be some handshake involved between the host and Cr50.

The method added by this CL to allow Host reads of the TPM fifo
assumes the following steps:

1. Host reads burstcount from Cr50 (which will be set to default 63)
2. Host reads 1st 10 bytes of the TPM response.
3. Cr50 will copy MIN(burstcount, msg_len) bytes into its I2CS HW fifo
4. Host computes msg_len and calculates amount of data still buffered
5. Host does a TPM fifo read of buffered data only
(The following steps are repeated until the response read is complete)
6. Host reads burstcount from STS register.
7. Host issues read of burscount bytes from TPM fifo
8. I2CS will copy burstcount amount of bytes in to I2CS HW fifo
9. TPM layer sets burstcount to MIN(63, remaining msg bytes)

The version register is treated similar to a fifo access. The data
written or the number of bytes is a don't care, but there must be
at least one byte of data written with the version register write.
In the case of reads, the host must read burstcount bytes of the
version register. If burstcount is longer than the Cr50 version string
there is no issue because the version register read function always
returns the number of bytes requested, stuffing in 0s once the end of
the version string is reached.

BRANCH=none
BUG=chrome-os-partner:40397
TEST=manual
Created test code in coreboot that exercises TPM register reads and
writes. In addition, created a means to spoof a TPM cmd send and
response read by Host. For these tests the header length is defined as
10 bytes and used 3 different payload lengths. The results for a
payload length of 256 and 39 (message < 63) are shown below. Note the
0xaa and 0x55 have been inserted by the TPM spoof code on the host to
mark the end of the header.

=================================================
Cr50 TPM Register Read tests
TPM Access = 0x0
TPM2 STS = 0x4003f80
TPM2 DID_VID = 0x281ae0
DID = 0x28, VID = 0x1ae0
Ver segment read 1, ret = 0
Version: B2:0 RO_A:0.0.1/84e2dde7 RW_A:0.0.1/cr50_v1.1.5151-acaef21+
=================================================
TPM Cmd: 266 bytes, Hdr = 10, Payload = 256 (last = ff)
TPM STS: Sending command_ready
fifo wr: burstcount = 63
fifo wr: Sent TPM Cmd: len = 266 bytes
TPM STS: Sending TPM GO
TPM STS: data_avail set
TPM STS: 04 00 3f d0: burst = 63
fifo rd: Msg_len = 266
fifo rd: Hdr Len = 10, fifo_adjust = 53
fifo rd: Drained Cr50 HW fifo of 53 bytes
fifo rd: burst = 63
fifo rd: burst = 63
fifo rd: burst = 63
fifo rd: burst = 14
fifo rd: complete 266 byte msg read
[0000]: 00 00 00 00 01 0a 00 00 aa 55 00 01 02 03 04 05
[0010]: 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15
[0020]: 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25
[0030]: 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35
[0040]: 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45
[0050]: 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55
[0060]: 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65
[0070]: 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75
[0080]: 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 85
[0090]: 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 95
[00a0]: 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 a5
[00b0]: a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 b5
[00c0]: b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 c5
[00d0]: c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 d5
[00e0]: d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 e5
[00f0]: e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 f5
[0100]: f6 f7 f8 f9 fa fb fc fd fe ff 00 00 00 00 00 00

=================================================
TPM Cmd: 49 bytes, Hdr = 10, Payload = 39 (last = 26)
TPM STS: Sending command_ready
fifo wr: burstcount = 63
fifo wr: Sent TPM Cmd: len = 49 bytes
TPM STS: Sending TPM GO
TPM STS: data_avail set
TPM STS: 04 00 3f d0: burst = 63
fifo rd: Msg_len = 49
fifo rd: Hdr Len = 10, fifo_adjust = 39
fifo rd: Drained Cr50 HW fifo of 39 bytes
fifo rd: complete 49 byte msg read
[0000]: 02 00 00 00 00 31 00 00 aa 55 00 01 02 03 04 05
[0010]: 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15
[0020]: 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25
[0030]: 26 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Change-Id: I0e05156d6012c6dc86844e4c0ea80cc04f45734a
Signed-off-by: Scott <scollyer@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/374528
Commit-Ready: Scott Collyer <scollyer@chromium.org>
Tested-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
2016-09-05 23:22:16 -07:00
Scott
ef4ccb2318 Cr50: I2CS TPM: Unify tpm_registers interface between SPI and I2C
Removed 3 TPM register definitions which were not used in
tpm_registers.c and added missing entries to the I2CS translation
table for TPM register address lookup.

Moved the SPI specific locality 0 offset from tpm_registers.c to
sps_tpm.c so the register defines in tmp_registers.c can be
common to both the SPS and I2CS interface.

BRANCH=none
BUG=chrome-os-partner:40397
TEST=manual
For I2CS verification on Reef AP console used the command 'i2cget
-y 8 0x50 <addr> b' to read both the TPM access and RID register.
For SPI verifcation updated Cr50 FW on Kevin and verified that the
AP successfully boots. Additionally, issued the command from the
Kevin console 'trunks_client --own' and got the following console
output without any errors being listed.
[INFO:tpm_utility_impl.cc(1692)] CreateStorageRootKeys: Created RSA SRK.
[INFO:tpm_utility_impl.cc(1735)] CreateStorageRootKeys: Created ECC SRK.

Change-Id: Ib0b70e22cd46de2c59bd2e73f3c9aebd661e66c4
Signed-off-by: Scott <scollyer@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/368621
Commit-Ready: Scott Collyer <scollyer@chromium.org>
Tested-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
2016-09-05 23:22:15 -07:00
Scott
e4f389a275 Cr50: Preliminary I2CS TPM2.0 driver
This CL includes changes in Cr50 required to support TPM via
the I2CS interface.

BRANCH=none
BUG=chrome-os-partner:40397
TEST=manual
Limited testing so far. Verified that the I2CS interface is
initialized properly and that register reads occur when
initiated on the AP console via command i2cget -y 8 0x50 0x1 w

Change-Id: I16ac17c7c82d420a384908e4b5a9867a3b24bc9e
Reviewed-on: https://chromium-review.googlesource.com/356241
Commit-Ready: Scott Collyer <scollyer@chromium.org>
Tested-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
2016-09-05 23:22:13 -07:00