How do I increase the colibri imx7 SPI bus frequency above 24MHz?

According to the i.MX 7Dual Family of Applications Processors Datasheet, Rev. 5, 07/2017 at page 10, the ecSPI data rate can reach 52 Mbit/s.

I started with the master polling ecspi example. I could easyily change the bus frequency up to 24MHz. But if I set a baudrate value higher than 24000000, the SPI SCLK signal frequency keeps stuck at 24MHz (measured electrically).

ecspi_init_config_t initConfig = {
    .baudRate = 24000000,
    .mode = ecspiMasterMode,
    .burstLength = ECSPI_MASTER_BURSTLENGTH,
    .channelSelect = BOARD_ECSPI_CHANNEL,
    .clockPhase = ecspiClockPhaseSecondEdge,
    .clockPolarity = ecspiClockPolarityActiveHigh,
    .ecspiAutoStart = ECSPI_MASTER_STARTMODE
};

By the way to make it work that fast, I had to set SRE and DSE bits.

void configure_ecspi_pins(ECSPI_Type* base)
{
...
    /* pad control */
    IOMUXC_SW_PAD_CTL_PAD_I2C2_SCL =    IOMUXC_SW_PAD_CTL_PAD_I2C2_SCL_PE_MASK  |
                    IOMUXC_SW_PAD_CTL_PAD_I2C2_SCL_PS(0)    |      /* pull down */
                    IOMUXC_SW_PAD_CTL_PAD_I2C2_SCL_DSE(3)   |
                    IOMUXC_SW_PAD_CTL_PAD_I2C2_SCL_SRE_MASK |
                    IOMUXC_SW_PAD_CTL_PAD_I2C2_SCL_HYS_MASK;

I tried to change to change the clock source. But It doesn’t affect the SCLK frequency.

uint32_t pre = -1;
uint32_t post = -1;
uint32_t root = -1;
//CCM_SetRootMux(CCM, ccmRootEcspi1, ccmRootmuxEcspiSysPllDiv2);
CCM_SetRootMux(CCM,ccmRootEcspi1 , ccmRootmuxEcspiSysPllPfd4);
CCM_SetRootDivider(CCM , ccmRootEcspi1, 1, 1);
CCM_GetRootDivider(CCM, ccmRootEcspi1, &pre, &post);
root = CCM_GetRootMux(CCM, ccmRootEcspi1);
ECSPI_SetSampClockSource(BOARD_ECSPI_BASEADDR, 0);

I’m not sure but I assume there is a mistake in the documentation or in the BSP. They contradict each other. The ecspi clock id is 102 in the FreeRTOS code and number 120 in i.MX 7 Dual Applications Processor Reference Manual. So I’m a bit confused.

The code in platform/drivers/inc/ccm_imx7d.h

enum _ccm_root_control
{
...
    ccmRootEcspi1 = (uint32_t)(&CCM_TARGET_ROOT102), /*!< ECSPI1 Clock control name.*/
    ccmRootEcspi2 = (uint32_t)(&CCM_TARGET_ROOT103), /*!< ECSPI2 Clock control name.*/
    ccmRootEcspi3 = (uint32_t)(&CCM_TARGET_ROOT104), /*!< ECSPI3 Clock control name.*/
    ccmRootEcspi4 = (uint32_t)(&CCM_TARGET_ROOT105), /*!< ECSPI4 Clock control name.*/
...
};

The clock root table that show we can even reach 80 MHz.
i.MX 7Dual Applications Processor Reference Manual p. 543
[upload|5BqM3QcfHgeKrPK+7151V+SSR58=]

The id 102 doesn’t belong to the ecspi clock.
i.MX 7Dual Applications Processor Reference Manual p. 581
[upload|z49EJ1Uld8XG8eJ79bEfubq0mqI=]

Actually the ecspi clock belongs to the id 120.
i.MX 7Dual Applications Processor Reference Manual p.582

So I’m wondering, whether you have a solution to get a SPI frequency above 24MHz ? I gave a modified copy of examples/imx7_colibri_m4/driver_examples/ecspi/ecspi_polling/master/main.c which I tried to change the SPI clock.

Thanks in advance,

Arnaud

Dear @arnaud_infoteam

Clarification

First i would like to resolve the confusion 102 vs. 120, it is no typo:

  • 120 is the Clock-Gating ID
    CCGR120 controls the clock gate for ECSPI1 ↠ graphics in the DRM p.551.
  • 102 is the position of the clock muxing register
    base address = 0x3038_8000 + (102 x 0x80) = 0x3038_B300 ↠ DRM p.543

Another thing to clarify: The default SPI on Colibri iMX7 is ECSPI3.

Register to Change

With your investigations you were pretty close to the solution. To go above 24MHz SCLK speed, you need to choose a different base clock in the register CCM_TARGET_ROOT104 (0x3038_B400). This controls the root clock for ECSPI 3 (↠ see DRM p. 543, 721, 757)

My tests

I did a simple test as follows

  • I added a loop to the default ecspi_polling example, so I couId repeatedly press ‘s’ to trigger another burst of SPI transfers.
  • I hooked up two terminal programs
    • one to Colibri UART-A (for U-Boot) and
    • one to Colibri UART-B (for the M4 application)
  • I booted the Colibri i.MX7 into U-Boot and started an M4 application to get the clocks up and running
  • I used the debugger to run my looping ecspi_polling example
  • Then I repeated the following steps
    • on the U-Boot command line, write to the clock root register
    • press ‘s’ in the other terminal to trigger another SPI burst on the M4 ECSPI
    • measure the SCLK frequency with a scope

Here is the U-Boot command sequence to read / write the CCM_TARGET_ROOT104 register:

Colibri iMX7 # md.l 0x3038b400 1
3038b400: 10000000                               ....

Colibri iMX7 # mw.l 0x3038b400 0x10010000 1
Colibri iMX7 # mw.l 0x3038b400 0x10000007 1
Colibri iMX7 # mw.l 0x3038b400 0x10000001 1
Colibri iMX7 # mw.l 0x3038b400 0x10010004 1
Colibri iMX7 # mw.l 0x3038b400 0x10010004 1
Colibri iMX7 # mw.l 0x3038b400 0x11010004 1
Colibri iMX7 # mw.l 0x3038b400 0x14010004 1
Colibri iMX7 # mw.l 0x3038b400 0x14000004 1
Colibri iMX7 # mw.l 0x3038b400 0x14000004 1
Colibri iMX7 # mw.l 0x3038b400 0x14000004 1
Colibri iMX7 # mw.l 0x3038b400 0x14000004 1
Colibri iMX7 # mw.l 0x3038b400 0x14000004 1
Colibri iMX7 # mw.l 0x3038b400 0x14000002 1

The SCLK frequency changed as expected. But when configuring high frequencies, it seemed the frequency did not follow properly the configuration (e.g. I configured for 48MHz, but measured 53MHz). So there might be some fine tuning required to configure the various dividers along the clock path.

Conclusion

I did not debug into your code, but as I see you tried to modify ccmRootEcspi1. Changing this to ccmRootEcspi3 might be enough to make your code work.
However, make sure you modify the CCM_TARGET_ROOT104 register (0x3038_B400).

Regards, Andy

Thanks a lot !