Initialization of iMX8M ECSPI2 TPM 2.0 device Infineon SLB9670 failed when running TPM self test

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Initialization of iMX8M ECSPI2 TPM 2.0 device Infineon SLB9670 failed when running TPM self test

8,321 Views
yuklin_soo
Contributor I

Hi,

I am trying to enable a TPM 2.0 device (Infineon SLB9670XQ2.0)  which is connected to the ECSPI2 bus of an IMX8MQ processor, and when booting up the target board, I encountered an issue that the initialization of the TPM device failed with the below error messages:

tpm_tis_spi spi1.0: 2.0 TPM (device-id 0x1B, rev-id 16)

2.0 TPM (device-id 0x1B, rev-id 16)

tpm tpm0: A TPM error (256) occurred attempting to generate an interrupt

tpm tpm0: [Firmware Bug]: TPM interrupt not working, polling instead

tpm tpm0: A TPM error (256) occurred continue selftest

tpm tpm0: starting up the TPM manually

tpm tpm0: tpm_transmit: tpm_recv: error -5

tpm tpm0: TPM self test failed

tpm_tis_spi: probe of spi1.0 failed with error -5

  

The TPM self test failed because the TPM device is not able to generate an interrupt. Display of kernel debugging messages shows that, prior to the TPM self test, the TPM driver failed to set the Global Interrupt Enable bit on the TPM Interrupt Enable register to 1.

 

To find out why the driver can’t write to a TPM register, we tried to monitor the SPI Slave Select GPIO pin on oscilloscope during the SPI data transfer (interrupt-driven PIO, not DMA) to/from the TPM device, we observed that the Slave Select pin can be pulled Low during data transfer and set to High when data transfer is completed, and therefore we believe the SS pin is not hindering the data transfer, and afterwards, when we proceed to monitor the SPI clock pin, we observed that there is no clock signal comes out from the pin at all, as a result, we suspect that the failure to write to a TPM register is due to no SPI clock signal to the TPM device during data transfer.

 

When investigating why there is no SPI clock signal generated for the TPM device, we noticed that the clock enable function tpm_tis_clkrun_enable()in the TPM TIS driver (kernel version 4.14.78) supports only LPC bus on Intel platform but not the ECSPI bus on NXP IMX8M platform. It looks like the current TPM TIS driver is missing the implementation to support the enable/disable of clock signals from ECSPI bus to the TPM device during data transfer. Below is the code of function tpm_tis_clkrun_enable(),

 

static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value)

{

        struct tpm_tis_data *data = dev_get_drvdata(&chip->dev);

        u32 clkrun_val;

 

        if (!IS_ENABLED(CONFIG_X86) || !is_bsw() ||

            !data->ilb_base_addr)

                return;

 

        if (value) {

                data->clkrun_enabled++;

                if (data->clkrun_enabled > 1)

                        return;

                clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET);

 

                /* Disable LPC CLKRUN# */

                clkrun_val &= ~LPC_CLKRUN_EN;

                iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET);

 

                /*

                 * Write any random value on port 0x80 which is on LPC, to make

                 * sure LPC clock is running before sending any TPM command.

                 */

                outb(0xCC, 0x80);

        } else {

                data->clkrun_enabled--;

                if (data->clkrun_enabled)

                        return;

 

                clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET);

 

                /* Enable LPC CLKRUN# */

                clkrun_val |= LPC_CLKRUN_EN;

                iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET);

 

                /*

                 * Write any random value on port 0x80 which is on LPC, to make

                 * sure LPC clock is running before sending any TPM command.

                 */

                outb(0xCC, 0x80);

        }

}

 

The schematic of IMX8M ECSPI2 pin interface:

 pastedImage_1.png

 

 The schematic of TPM device interface to the IMX8M ECSPI2:

 pastedImage_2.png

 

 The ECSPI2 configurations in the device tree file is as shown below:

 

pinctrl_ecspi2: ecspi2grp {

        fsl,pins = <

                MX8MQ_IOMUXC_ECSPI2_MOSI_ECSPI2_MOSI    0x19

                MX8MQ_IOMUXC_ECSPI2_MISO_ECSPI2_MISO    0x19

                MX8MQ_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK    0x19

                MX8MQ_IOMUXC_NAND_CE1_B_GPIO3_IO2       0x19

                MX8MQ_IOMUXC_NAND_CE2_B_GPIO3_IO3       0x17059

        >;

};

 

pinctrl_ecspi2_cs: ecspi2cs {

        fsl,pins = <

//              MX8MQ_IOMUXC_ECSPI2_SS0_ECSPI2_SS0      0x82

                MX8MQ_IOMUXC_ECSPI2_SS0_GPIO5_IO13      0x19

        >;

};

 

&ecspi2 {

        #address-cells = <1>;

        #size-cells = <0>;

        fsl,spi-num-chipselects = <1>;

        cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;

//      cs-gpios = <0>;

        pinctrl-names = "default";

        pinctrl-0 = <&pinctrl_ecspi2 &pinctrl_ecspi2_cs>;

        dmas = <&sdma1 3 7 0>, <&sdma1 4 7 0>;

        dma-names = "rx", "tx";

        status = "okay";

 

        tpm0: slb9670@0 {

                compatible = "infineon,slb9670";

                reg = <0>;

                resets = <&tpm_reset>;

                spi-max-frequency = <38000000>;

                interrupt-parent = <&gpio3>;

                interrupts = <3 IRQ_TYPE_LEVEL_LOW>;

                status = "okay";

        };

};

 

Really appreciate if someone can help point out what could have done wrong or can provide any solution or patch to this problem.

0 Kudos
Reply
4 Replies

6,828 Views
igorpadykov
NXP Employee
NXP Employee

Hi Alex

first one can try with ecspi2 example without sdma :

linux-imx6/arch/arm64/boot/dts/freescale/imx8mq-nitrogen8m.dts

linux-imx6/imx8mq-nitrogen8m.dts at boundary-imx_4.14.x_2.0.0_ga · boundarydevices/linux-imx6 · GitH... 

Regarding sdma, one can recheck sdma ecspi2 channel numbers in Table 7-3. SDMA1 event mapping

i.MX8MDQ Reference Manual. Use sdma linux dts documentation

linux-imx6/fsl-imx-sdma.txt at boundary-imx_4.14.x_2.0.0_ga · boundarydevices/linux-imx6 · GitHub 

and sai1 sdma example (channel number can be found in Table 7-4. SDMA2 event mapping)

linux-imx6/fsl-imx8mq-evk.dts at boundary-imx_4.14.x_2.0.0_ga · boundarydevices/linux-imx6 · GitHub 
https://www.nxp.com/docs/en/reference-manual/IMX8MDQLQRM.pdf

Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply

6,828 Views
yuklin_soo
Contributor I

Hi Igor,

Thank you for the reply.

The ECSPI2 data transfer is using the interrupt-driven method (without SDMA).

I commented out the below two lines (dmas):

&ecspi2 {

        #address-cells = <1>;

        #size-cells = <0>;

        fsl,spi-num-chipselects = <1>;

        cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;

//      cs-gpios = <0>;

        pinctrl-names = "default";

        pinctrl-0 = <&pinctrl_ecspi2 &pinctrl_ecspi2_cs>;

//       dmas = <&sdma1 3 7 0>, <&sdma1 4 7 0>;   < == commented out

//       dma-names = "rx", "tx";                                   < == commented out

        status = "okay";

and now I am able to see the tpm0 device

# ls -l /dev/tpm*
crw------- 1 root root 10, 224 May 24 11:56 /dev/tpm0
crw------- 1 root root 252, 65536 May 24 11:56 /dev/tpmrm0
# cat /proc/interrupts | grep tpm
137: 0 0 0 0 gpio-mxc 3 Level tpm0

#

These two lines were previously added to suppress the error message:

[   12.728854] spi_imx 30830000.ecspi: dma setup error -19, use pio

 

Besides that, I went through the MCIMX51RM document, and found the DATA CTL field in CONFIGREG, updated the SPI driver to make sure that the ECSPI2 (SPI 1 channel) is activated and set the inactive state of the MOSI line to stay Low.

0 Kudos
Reply

6,828 Views
yuklin_soo
Contributor I

I want to take back my previous claim that there are no signals come out from the SCLK pin, after adjusting my oscilloscope bandwidth to full, I am now able to see the SPI clock signals sent to the TPM device.

Another thing I noticed is that, when data is transferred between the SPI master and the TPM slave device during the TPM driver initialization:

SPI MOSI - is set to HIGH and data bits sent through this line are superimposed on the 3.3V signal

SPI MISO - is set to LOW and data bits sent through this line properly

When initialization process completed and the SPI interface is idle,

SPI MOSI - is idle HIGH

SPI MISO - is idle LOW

The current issue is that the TPM driver is able to read from a TPM register (through MISO) and Not able to write to a TPM register (though MOSI). Therefore, it seems the problem is on the MOSI line, is it because the data is sent through a MOSI line which is always at logic level HIGH, and that is causing the TPM device to ignore the data sent?

0 Kudos
Reply

6,549 Views
jiangyaqiang
Contributor V

HI,

   I got a question about the ECSPI2 clock. I'm aslo using ECSPI2, and found that no clock output.

   How do you fix the no clock problem ? just set the oscilloscope ?

0 Kudos
Reply