TPM on SPI2 in Uboot


Some good news - I am able to see/talk to/probe/etc. a Winbond W25Q64CV chip connected to SPI1 on the 40-pin GPIO connector on my Nano devkit. I can do a Read JEDEC ID, Read SFDP Register (0), etc., using sspi, and see the signals on my Saleae analyzer. ‘sf probe 1:0’ works, too.

I had to enable spi@7000d400 in the U-Boot p3450 DTS (status=“okay”, and max-spi-clock = 20MHz) and add the spi1 alias, rebuilt/reflash U-Boot, and then force the SPI1 pinmux regs (0x70003050/54/58/5c) to 0x6004/0x6044 at the U-Boot prompt, just as you’ve done for SPI2.
But that’s it - I don’t know why my Winbond SPI board wouldn’t work on SPI2 on the 40-pin GPIO connector - maybe some GPIO conflict, etc. But I can talk to a SPI chip on the 40-pin J41 with the tegra114_spi driver, so that’s good.

If I add CONFIG_SPI_FLASH_WINBOND=y to my P3450 defconfig, I can also get ‘sf probe’ to return the Winbond chip specifics, and do a ‘sf read’, etc. Note that this is all with our L4T U-Boot from R32.7.x.

I suspect you can’t move your TPM to SPI1, but if you have a proto board you can hook up to SPI1 to test out under U-Boot, that might help you compare the SPI2 mux/GPIO/etc. registers to SPI1 to see what might be blocking progress.



This is good news. At least we know that the driver does work in uboot on a Nano.

It sounds like you tried to connect with SPI2 on the 40 pin and it didn’t work is that correct?

We are to late in the HW design to move the TPM to SPI1, so I have to make the FW work with SPI2. So I will continue to look into it. But this does make it sounds like there is a way with the resources we have.

We haven’t worked with the devkit in quite a while, but I do still have one that I can run some tests with to reproduce your results.

Correct, I tried the SPI2 pins first this morning, w/o success. Then moved to SPI1 and it worked. If I have time next week I’ll try to compare SPI1 to SPI2 regs and see what the secret might be.


We are in the process of reworking one of our boards to swap the TPM from SPI2 to SPI1. We will at least be able to see if the driver and DT works for our device on SPI1. However we are already passed the point where we can make changes to the HW so we can’t just do a swap if it does work.

I tried on Friday to compare the registers if I switched to SPI1 from SPI2 and I didn’t see any difference in the registers we had already been looking at. There are a few other mentions of SPI1 and SPI2 in the TRM but they seem to have the same values as the 308 and 328 offsets.


There are no differences intrinsically between SPI1 and SPI2 in the T210 SoC that I know of, Joseph. I suspect that whatever is keeping SPI2 from working is some initial setting in GPIO, mux, pad cfg, pulls,
CAR, etc. that is impeding the signal(s) somehow. AFAIK, there’s no reason that SPI2 shouldn’t work as well as SPI1. It will be interesting to see what you see when you move the TPM to SPI1, even if temporarily. It’s piqued my interest, and I’ll look into it as time permits, but I don’t have the BW to devote to too deep an investigation, unfortunately.


Understood. Thank you for the test that you did to give us some more areas to look at.

So we reworked a board and switched out TPM from SPI2 to SPI1. I changed the Pinmux and both uboot and kernel DTs to point at SPI1 instead (no other changes).
I flashed the reworked board and the TPM2 Init call worked without changing any registers:

Tegra210 (P3450-0000) # tpm2 init
Warning: SPI 'spi@7000d400' requested clock 500000, actual clock 498701
tpm_tis_spi_probe() SPI TPMv2.0 found (vid:15d1, did:001d, rid:36)

So this proves that we can use the drivers to comunicate with our TPM from u-boot. We still need to discover what the difference between SPI1 and SPI2 are to try and configure them the same.


Well done. Perhaps @WayneWWW can inquire with our HW folk about any external diffs in SPI1 and SPI2 on Nano CVM/CVB, while you look into any SW diffs from pinmux/GPIO DTBs, CAR, etc.


@TWarren @WayneWWW

I am not an expert on these registers, but what I see when I tested on SPI1 (and changed the PINMUX) was that the 0x70003050 (SPI1) registers matched the SPI2 registers except that they had 0xe0xx instead of 0x60xx. I was looking at the TRM and it shows that this bit that is different is “E_PREEMP” and on SPI1 it is enabled and on SPI2 it is not even an option. I am not an EE so the name of the bit doesn’t mean much to me, but could this be something? Other than this bit when we have the TPM on SPI1 the other registers match what we have for SPI2 registers. I will continue to look, but so far this is the one difference I am seeing.


@TWarren @WayneWWW

I captured the following registers that I can think of having to do with SPI1 and SPI2.

I captured them all on our board with the TPM on SPI1 and on our board with the TPM on SPI2. Everywhere there are differences make sense to me except for bit 15 on SPI1 being high as I said in my previous post, as well as CS1_0 being 0xe020 vs 0x6021 (I did try and set it to 0x6020 and it still didn’t work). All other changes seem are just SPI1 vs SPI2 clocks being enabled or the reset GPIO being setup as an output GPIO.

Register Name Register Addr SPI1 (Working) SPI2 (Not Working)
CLK_RST_CONTROLLER_CLK_OUT_ENB_H_0 0x60006014 0x020082c1 0x20090c1
CLK_RST_CONTROLLER_CLK_SOURCE_SPI1_0 0x60006134 0xc0000098 0xc0000000
CLK_RST_CONTROLLER_CLK_SOURCE_SPI2_0 0x60006118 0xc0000000 0xc0000098
CLK_RST_CONTROLLER_RST_DEV_H_SET_0 0x60006308 0x0 0x0
CLK_RST_CONTROLLER_RST_DEV_H_CLR_0 0x6000630c 0x0 0x0
CLK_RST_CONTROLLER_CLK_ENB_H_SET_0 0x60006328 0x020082c1 0x020090c1
CLK_RST_CONTROLLER_CLK_ENB_H_CLR_0 0x6000632c 0x020082c1 0x020090c1
SPI1_CS0 0x70000ad4 0x0 0x0
SPI1_CS1 0x70000ad8 0x0 0x0
SPI1_MISO 0x70000adc 0x0 0x0
SPI1_MOSI 0x70000ae0 0x0 0x0
SPI1_SCK 0x70000ae4 0x0 0x0
SPI2_CS0 0x70000ae8 0x0 0x0
SPI2_CS1 0x70000aec 0x0 0x0
SPI2_MISO 0x70000af0 0x0 0x0
SPI2_MOSI 0x70000af4 0x0 0x0
SPI2_SCK 0x70000af8 0x0 0x0
PINMUX_AUX_SPI1_MOSI_0 0x70003050 0xe024 0xe035
PINMUX_AUX_SPI1_MISO_0 0x70003054 0xe064 0xe035
PINMUX_AUX_SPI1_SCK_0 0x70003058 0xe024 0xe035
PINMUX_AUX_SPI1_CS0_0 0x7000305c 0xe024 0xe035
PINMUX_AUX_SPI1_CS1_0 0x70003060 0xe020 0xe035
PINMUX_AUX_SPI2_MOSI_0 0x70003064 0x6024 0x6024
PINMUX_AUX_SPI2_MISO_0 0x70003068 0x6064 0x6064
PINMUX_AUX_SPI2_SCK_0 0x7000306c 0x6024 0x6024
PINMUX_AUX_SPI2_CS0_0 0x70003070 0x6024 0x6024
PINMUX_AUX_SPI2_CS1_0 0x70003074 0x6021 0x6021
ACTMON_APB_CTRL_0 0x702EC940 0x0 0x0
GPIO_CNF_1 (Port B) 0x6000d004 0x0 0x0
GPIO_CNF_2 (Port C) 0x6000d008 0x10 0x0
GPIO_OE_1 (Port B) 0x6000d014 0x0 0x0
GPIO_OE_2 (Port C) 0x6000d018 0x10 0x0
GPIO_OUT_1 (Port B) 0x6000d024 0x0 0x0
GPIO_OUT_2 (Port C) 0x6000d028 0x10 0x0
GPIO_IN_1 (Port B) 0x6000d034 0x0 0x0
GPIO_IN_2 (Port C) 0x6000d038 0x0 0x0
GPIO_INT_STA_1 (Port B) 0x6000d044 0x0 0x0
GPIO_INT_STA_2 (Port C) 0x6000d048 0x0 0x0
GPIO_INT_ENB_1 (Port B) 0x6000d054 0x0 0x0
GPIO_INT_ENB_2 (Port C) 0x6000d058 0x0 0x0
GPIO_INT_LVL_1 (Port B) 0x6000d064 0x0 0x0
GPIO_INT_LVL_2 (Port C) 0x6000d068 0x0 0x0
GPIO_INT_CLR_1 (Port B) 0x6000d074 0x0 0x0
GPIO_INT_CLR_2 (Port C) 0x6000d078 0x0 0x0
GPIO_CNF_1 (Port DD) 0x6000d704 0x1 0x1
GPIO_OE_1 (Port DD) 0x6000d714 0x1 0x1
GPIO_OUT_1 (Port DD) 0x6000d724 0x1 0x1
GPIO_IN_1 (Port DD) 0x6000d734 0x0 0x0
GPIO_INT_STA_1 (Port DD) 0x6000d744 0x0 0x0
GPIO_INT_ENB_1 (Port DD) 0x6000d754 0x0 0x0
GPIO_INT_LVL_1 (Port DD) 0x6000d764 0x0 0x0
GPIO_INT_CLR_1 (Port DD) 0x6000d774 0x0 0x0

@jjsalzano @ShaneCCC @WayneWWW

Sorry, I’m a SW guy, and I too have no idea what ‘E_PREEMP’ is used for, nor why it’s on SPI1 and not SPI2 on T210. Shane/Wayne can find out from the appropriate HW person, I’m sure.
Sometimes the TRM is incomplete - can you try setting that bit on SPI2 and see if it sticks, and if SPI2 TPM access then works? Or turn it off on SPI1 and see if TPM access then fails? All I can think of right now.


@TWarren I didn’t try turning it off for SPI1, I can try that now. I did try turning it on for SPI2 and it didn’t change. It seems like a read only bit.

I just tried changing 0x70003050-0x70003060 to have bit 15 low (now matches exactly 0x70003064-0x70003074) and “tpm2 info” still works.
So now there are no differences between the registers that I can tell, but still SPI1 works. Maybe there is a HW change that happens after the bootloaders that we need to set a GPIO or something else earlier?

Do you try the REG configure like boot to the system.
Below is working configure after boot to ubuntu.

sudo cat /sys/kernel/debug/tegra_pinctrl_reg
Bank: 1 Reg: 0x70003050 Val: 0x0000e044 -> spi1_mosi_pc0
Bank: 1 Reg: 0x70003054 Val: 0x0000e044 -> spi1_miso_pc1
Bank: 1 Reg: 0x70003058 Val: 0x0000e044 -> spi1_sck_pc2
Bank: 1 Reg: 0x7000305c Val: 0x0000e048 -> spi1_cs0_pc3
Bank: 1 Reg: 0x70003060 Val: 0x0000e048 -> spi1_cs1_pc4
Bank: 1 Reg: 0x70003064 Val: 0x00006044 -> spi2_mosi_pb4
Bank: 1 Reg: 0x70003068 Val: 0x00006044 -> spi2_miso_pb5
Bank: 1 Reg: 0x7000306c Val: 0x00006044 -> spi2_sck_pb6
Bank: 1 Reg: 0x70003070 Val: 0x00006044 -> spi2_cs0_pb7
Bank: 1 Reg: 0x70003074 Val: 0x00006044 -> spi2_cs1_pdd0

Hi Shane,
Yes we did try to change the uboot registers to match what they are in ubuntu, however we didn’t see any different.
SPI1 also changes once it boots to Ubuntu but it still works in u-boot with the same register values as the SPI2 registers have.

@TWarren @ShaneCCC @WayneWWW

Any more insights as to why the 2 busses differ with the same register values? We tried matching the registers between SPI1 and SPI2 in uboot and only SPI1 works. We also tried to match the uboot registers of SPI2 to what is in the OS, also doesn’t work.

We are having to look at alternatives to secure our solution as this is blocking our progress on getting approval for release. We would like to use a measured boot though if we can get this working.