This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM6442: GPMC timings under Linux are twice as long as anticipated

Part Number: AM6442

Tool/software:

Hello,

I want to make use of the following GPMC configuration regarding the clock:

  • The external GPMC protocols are to be syncronous.
  • The external GPMC clock is to be free-running.
  • The clock frequency is to be 66.67MHz for first experiments, later higher.

What I did in order to accomplish that so far:

  • In the pinmux-section (main_pmx0) of the device tree I set AM64X_IOPAD(0x007c, PIN_OUTPUT, 4). This - especially mode 4 - is needed in order to output a clock signal bypassing the GPMC module, so that the clock is not being manipulated and free-running.
  • In the gpmc0-section of the device tree I configured the clock like that

        assigned-clocks = <&k3_clks 80 0>;
        assigned-clock-parents = <&k3_clks 80 1>;
        assigned-clock-rates = <66666667>;

  • At that point I can already confirm a free running clock of 66.67MHz at the right IO pad.
  • I did add various parameters for the according ChipSelects by means of a gpmc-child definition within the device tree configuration. Here is some exemplary setting for CS0:

        fpga@0,0{
                reg = <0 0 0x001000000>;
                gpmc,mux-add-data = <2>;        // AD multiplexed mode with a single address phase.
                gpmc,device-width = <2>;        // 16 Bit
                gpmc,burst-length = <0>;        // No bursts.
                gpmc,wait-on-read = <0>;        // No wait on read.
                gpmc,wait-on-write = <0>;       // No wait on write.
                gpmc,sync-clk-ps = <15000>;
                gpmc,sync-read;
                gpmc,sync-write;
                gpmc,cs-on-ns = <0>;            // 0 clock ticks. CSONTIME - Immediate ChipSelect assertion without any delay.
                gpmc,cs-rd-off-ns = <105>;      // 7 clock ticks. CSRDOFFTIME - The clock number CS will be deasserted during read.
                gpmc,cs-wr-off-ns = <60>;       // 4 clock ticks. CSWROFFTIME - The clock number CS will be deasserted during write.
                gpmc,adv-on-ns = <0>;           // 0 clock ticks. ADVONTIME - The clock number the ADV signal will be asserted.
                gpmc,adv-rd-off-ns = <45>;      // 3 clock ticks. ADVRDOFFTIME - The clock number the ADV signal will be deasserted during read.
                gpmc,adv-wr-off-ns = <45>;      // 3 clock ticks. ADVWROFFTIME - The clock number the ADV signal will be deasserted during write.
                gpmc,wr-data-mux-bus-ns = <45>; // 3 clock ticks. WRDATAONADMUXBUS - The clock number the written data will appear or the address is removed.
                gpmc,oe-on-ns = <75>;           // 5 clock ticks. OEONTIME - The clock number the OE will be asserted during read.
                gpmc,oe-off-ns = <105>;         // 7 clock ticks. OEOFFTIME - The clock number the OE will be deasserted during read.
                gpmc,we-on-ns = <0>;            // 0 clock ticks. WEONTIME - The clock number the WE will be asserted during write.
                gpmc,we-off-ns = <60>;          // 4 clock ticks. WEOFFTIME - The clock number the WE will be deasserted during write.
                gpmc,rd-cycle-ns = <120>;       // 8 clock ticks. RDCYCLETIME - The number of clocks a read takes.
                gpmc,wr-cycle-ns = <60>;        // 4 clock ticks. WRCYCLETIME - The number of clocks a write takes.
                gpmc,wr-access-ns = <60>;       // 4 clock ticks. WRACCESSTIME - The number of clocks a write takes.
                gpmc,access-ns = <105>;         // 7 clock ticks. RDACCESSTIME - The clock number the first data word will be sampled during read.
                gpmc,bus-turnaround-ns = <15>;  // 1 clock tick. BUSTURNAROUND - The number of clock ticks inserted between accesses.
        };

  • When the address window associated with CS0 is being accessed, there's indeed some plausible activity on the GPMC Interface. However, as it turns out, all times are twice as long as they are supposed to be. I.e.where a single clock cycle is expected, there are two clock cycles passing by. 

There are some pitfalls I'm aware of. One is the setting of clock configurations within the CONFIG1_i register of the GPMC module of the according ChipSelect.

I'm using the omap-gpmc driver with enabled additional debugging output. I'm receiving the following relevant configuration information here:

[   23.128965] gpmc cs0 timings configuration:
[   23.128972] gpmc,cs-on-ns = <0>; /* 0 ns - 0 ns; 0 ticks */
[   23.128980] gpmc,cs-rd-off-ns = <105>; /* 91 ns - 105 ns; 7 ticks */
[   23.128988] gpmc,cs-wr-off-ns = <60>; /* 46 ns - 60 ns; 4 ticks */
[   23.128996] gpmc,adv-on-ns = <0>; /* 0 ns - 0 ns; 0 ticks */
[   23.083691] GPMC CS0: adv_wr_off       :   3 ticks,  45 ns (was   6 ticks)  45 ns
[   23.099261] GPMC CS0: adv_aad_mux_on   :   0 ticks,   0 ns (was   1 ticks)   0 ns
[   23.128536] GPMC CS0: adv_aad_mux_rd_off:   0 ticks,   0 ns (was   2 ticks)   0 ns
[   23.128568] GPMC CS0: adv_aad_mux_wr_off:   0 ticks,   0 ns (was   2 ticks)   0 ns
[   23.128577] GPMC CS0: oe_on            :   5 ticks,  75 ns (was   6 ticks)  75 ns
[   23.128587] GPMC CS0: oe_off           :   7 ticks, 105 ns (was  16 ticks) 105 ns
[   23.128596] GPMC CS0: oe_aad_mux_on    :   0 ticks,   0 ns (was   1 ticks)   0 ns
[   23.128625] GPMC CS0: oe_aad_mux_off   :   0 ticks,   0 ns (was   3 ticks)   0 ns
[   23.128634] GPMC CS0: we_on            :   0 ticks,   0 ns (was   5 ticks)   0 ns
[   23.128641] GPMC CS0: we_off           :   4 ticks,  60 ns (was  16 ticks)  60 ns
[   23.128650] GPMC CS0: rd_cycle         :   8 ticks, 120 ns (was  17 ticks) 120 ns
[   23.128659] GPMC CS0: wr_cycle         :   4 ticks,  60 ns (was  17 ticks)  60 ns
[   23.128667] GPMC CS0: access           :   7 ticks, 105 ns (was  15 ticks) 105 ns
[   23.128675] GPMC CS0: page_burst_access:   0 ticks,   0 ns (was   1 ticks)   0 ns
[   23.128683] GPMC CS0: bus_turnaround   :   1 ticks,  15 ns (was   0 ticks)  15 ns
[   23.128691] GPMC CS0: cycle2cycle_delay:   0 ticks,   0 ns (was   0 ticks)   0 ns
[   23.128699] GPMC CS0: wr_data_mux_bus  :   3 ticks,  45 ns (was   7 ticks)  45 ns
[   23.128707] GPMC CS0: wr_access        :   4 ticks,  60 ns (was  15 ticks)  60 ns
[   23.128716] GPMC CS0: wait_monitoring  :   0 ticks,   0 ns (was   0 ticks)   0 ns
[   23.128724] GPMC CS0: clk_activation   :   0 ticks,   0 ns (was   0 ticks)   0 ns
[   23.128779] GPMC CS0 CLK period is 15 ns (div 1)
[   23.128790] gpmc cs0 after gpmc_cs_set_timings:
[   23.128869] cs0 GPMC_CS_CONFIG1: 0x28001200
[   23.128877] cs0 GPMC_CS_CONFIG2: 0x00040700
[   23.128882] cs0 GPMC_CS_CONFIG3: 0x00030300
[   23.128887] cs0 GPMC_CS_CONFIG4: 0x04000705
[   23.128892] cs0 GPMC_CS_CONFIG5: 0x00070408
[   23.128897] cs0 GPMC_CS_CONFIG6: 0x84030001

I red-colored some important bit positions within the reported CONFIG registers.

To start with  GPMC_CS_CONFIG2, this 4 is refering to the cs-wr-off-ns time (actually, the width of the CS0 during a write here). This is supposed to be 4 clock ticks resp. 60ns. So this setting seems to be well ok. However, the actual pulse width of CS0 is 120ns or 8 clock ticks - so twice as long as it should be. This is certainly the case for all other timings as well (although I did not check all of them in detail), but this should serve as an example here.

GPMC_CS_CONFIG1 is the next important register. Bits 1:0 represent the GPMCFCLKDIVIDER. My understanding is, that in case GPMCFCLKDIVIDER is set to  1, for instance, the GPMC system is running at half the FCLK and hence also half the output clock at the pad (provided the pad is using the bypassed FCLK, which is the case here).  So this could be a potential issue here and explain the stretched timings. However, GPMCFCLKDIVIDER is set to  0, which corresponds to a divider of 1. So everything should be fine here.

Bit 4 of GPMC_CS_CONFIG1 represents TIMEPARAGRANULARITY. When set, it stretches access timings by a factor of two, which is probably also leading to the effect I'm seeing. However, according to the output, bit 4 is cleared as well. Btw., I did also play with that setting, and when  TIMEPARAGRANULARITY is set to 1, I'm seeing that the CS0 pulse width is 240ns instead of the expected 60ns - so four times longer.

Now, the question is: What might be leading to that behavior that I'm seeing here and what is perhaps missing in the configuration?

Thanks for any insights,

Mario

  • A quick update on that:

    It seems I found the root-cause of the behavior. In fact, the effect of the doubled times do not apply to all parameters, but just the ChipSelect. As it turns out, the GPMC module is driving two back-to-back transfers in my initial test case. This is because I did write a 32 bit value. Therefore I did see a ChipSelect that is twice as long active as it should be. When I force writing a 16 bit value, I get the proper length of the active ChipSelect.

    Nonetheless it is a little bit strange as I did specify the BUSTURNAROUND parameter (or gpmc,bus-turnaround-ns in the device tree file) to be 1 clock cycle. But perhaps there are some more things to add here. I'm going to check that further.

  • In order to conclude that matter:

    It is not parameter gpmc,bus-turnaround-ns that is defining the space between back-to-back accesses, but  gpmc,cycle2cycle-delay-ns together with at least gpmc,cycle2cycle-samecsen in order to apply this for the same ChipSelect as well (possibly also gpmc,cycle2cycle-diffcsen). So assuming the gpmc child section fpga@0,0 quoted above, adding the following is clearly separating back-to-back accesses by 15ns resp. a single clock at 66.67MHz then:

                    gpmc,cycle2cycle-delay-ns = <15>;
                    gpmc,cycle2cycle-diffcsen;
                    gpmc,cycle2cycle-samecsen;