Issue enabling TPM 2.0 on RPI

J. Holland joh.ho at
Mon Mar 30 11:23:19 CEST 2020


I stumbled on the same problem and found a solution.

The problem is, while there is a driver for the RPi SPI controller (BCM2835) in
the linux kernel [1] and also a fitting device tree overlay in the Raspbian fork
[2], this driver is missing for u-boot.

As you suggested, the solution is using the soft-spi driver which uses bit
banging. This is possible since the GPIO driver is imlemented. Now this soft-spi
driver is not really mature which leads to your problems.

> I tried to lower the frequency to 1MHZ but without success.

This is not the cause for your problem. However, you need to set the frequency
using "spi-delay-us" which is documented wrongly here [3]. Basically, it is not
the time between CS transitions, but the time that is (additionally) waited
between clock cycles. Without any delay, the clock frequency seems to be around
1MHz, by chance. With spi-delay-us = 1, I get about 200-250 kHz.

Your problem is the SPI mode. The Infineon TPM SLB9670 always operates at
CPOL=0,CPHA=0 (mode 0) [4, see 7.4.6]. By default, the soft-spi driver uses
CPOL=1 (hardcoded). Furthermore, when you set the mode to CPHA=0 (default), the
driver uses CPHA=1 and vice versa!

While technically you could inverse the clock signal in the device tree to get
CPOL=0, you shouldn't because a) the initial state will still be high (active)
and b) it is counter intuitive.

I submitted a patch [5] which makes the driver honor the SPI mode settings.
Since the default is mode 0, you do not need to add anything to your device

> I have the following response :
>tpm_tis_spi_probe : missing reset GPIO

As pointed out by Miquel Raynal, this is just a warning. As documented here [6],
you can use "gpio-reset" in your device tree to specify your pin. Pay attention
that you inverse its polarity (gpio-reset = <&gpio 24 1>;) or the TPM will not
answer. If you use a Let's Trust TPM board, the reset line is GPIO 24 (pin 18).
On an Infineon Iridium board, it should be GPIO 4 (pin 7).

You can easily test if your TPM is working by issuing the following commands
tpm2 init
tpm2 startup TPM2_SU_CLEAR
tpm2 get_capability 0x6 0x106 0x200 2

This should give you 0x534c4239, 0x36373000 which is hex for "SLB6970"

For anyone interested, I use the following device tree overlay. It is not yet
compatible with the Raspbian kernel, so after booting raspbian, you cannot
use the TPM anymore.

My device tree overlay:

/dts-v1/; /plugin/;

/ {
     compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";

     fragment at 0 {
         target = <&spi0>;
         __overlay__ {
             compatible = "spi-gpio";
             pinctrl-names = "default";
             pinctrl-0 = <&spi0_gpio7>;
             gpio-sck = <&gpio 11 0>;
             gpio-mosi = <&gpio 10 0>;
             gpio-miso = <&gpio 9 0>;
             cs-gpios = <&gpio 7 0>;
             spi-delay-us = <0>;
             #address-cells = <1>;
             #size-cells = <0>;
             status = "okay";

             tpm: tpm at 1 {
                 compatible = "tis,tpm2-spi", "infineon,slb9670";
                 reg = <1>;
                 gpio-reset = <&gpio 24 1>;
                 #address-cells = <1>;
                 #size-cells = <0>;
                 status = "okay";


     fragment at 1 {
         target = <&spi0_gpio7>;
         __overlay__ {
             brcm,pins = <7 8 9 10 11 24>;
             brcm,function = <0>;

     fragment at 2 {
         target = <&spidev1>;
         __overlay__ {
             status = "disabled";


More information about the U-Boot mailing list