SPI on LS connector not able to configure to Higher frequency


#1

Facing issue with SPI on LS connector,If we set the frequency to 16 MHZ its jumping to 13.3 MHZ.

Is there any parameters need to set to get the exact frequency?
@guodong @Loic Can you please help me on this?


Hikey960 board SPI on LS connector not able to configure to Higher frequency
#2

Facing issue with SPI on LS connector,If we set the frequency to 16 MHZ its jumping to 13.3 MHZ.
Is there any parameters need to set to get the exact frequency?

@guodong @Loic Can you please help me on this?


#3

Since SPI is a synchronous interface, there is usually no problem if frequency is not accurate.
The SPI clock is derived from the SPI controller clock on which prescalers/dividers are applied.
Depending master clock and prescaler/divider ranges, you can meet more or less the targeted SPI frequency.

For hikey960, clock adjustment take place in calculate_effective_freq function. Basically, it retrieves the master clock (clk_get_rate(pl022->clk)) and try every possible combinations of the prescaler/divider values (cpsdvsr, scr registers) and select the ‘best’ couple.


#4

@Loic ,Thanks for your suggestion i have modified the method calculate_effective_freq as per my requirement with that i am able to get the 16MHZ.

I have added that modified code below,with earlier logic frequency settings was jumping in larger gap.
in the modified code i have added my required acceptable difference with this able to get the 16MHZ.
and also verified for different speed its working fine.
Verified for 8MHZ,16MHZ and 20MHZ

    /*
     * best_freq will give closest possible available rate (<= requested
     * freq) for all values of scr & cpsdvsr.
     */
    while ((cpsdvsr <= CPSDVR_MAX) && !found) {
            while (scr <= SCR_MAX) {
                    tmp = spi_rate(rate, cpsdvsr, scr);
        diff = tmp > freq ? (tmp - freq):(freq-tmp);
        if(tmp == freq){
            best_freq = tmp;
            best_cpsdvsr = cpsdvsr;
            best_scr = scr;
            found=1;
            break;
        } else if (diff <= 100000){
            best_freq = tmp;
            best_cpsdvsr = cpsdvsr;
            best_scr = scr;
            found=1;
            break;
        }else if (diff <= 500000){
            best_freq = tmp;
            best_cpsdvsr = cpsdvsr;
            best_scr = scr;
            found=1;
            break;
        } else if (diff <= 1000000){
            best_freq = tmp;
            best_cpsdvsr = cpsdvsr;
            best_scr = scr;
            found=1;
            break;
          }
          scr++;
      }
      cpsdvsr++;
      scr=0;
    }