8 Replies Latest reply on Nov 13, 2014 1:34 PM by Intel_Alvarado

    Sources for /dev/spidev5.1 and what it calls

    KurtE

      As I have mentioned in a few other threads, I am trying to understand how the SPIDEV driver works as to understand it's performance and feature set.

       

      Some of the things I would like to understand include:

       

      Why the limit for the speed appears to be about: 6.25mhz.  If I try to a set to 8mhz it does not change the output speed and if I then do a query for the max speed it still reports the 6.25mhz

       

      Why when I to output multiple bytes there is a gap of time between bytes which is typically longer than the time it took to output the actual bytes.

       

      How if at all can I control the CS pin(s).  There is a field in the transfer structure for doing some of this, but my impression is that it does not currently do anything.

       

      wordsize (msg.bits_per_word) - is it implemented?

       

      ...

       

      So assumption is if I build a complete image from the sources (which I did), that the source files for the spidev is somewhere in the tree.   Any Hints?

      Also when I was first looking through the sources, I think I found it once, but the actual driver then appeared to simply call off to some other probably lower level drivers.  Which ones?  Are the sources there somewhere?

       

      Also is there some form of document which describes the SPI subsystem of the Edison?  Is it similar to what is shown for the Atom processor as described in the Galileo documents?

       

      Thanks

        • 1. Re: Sources for /dev/spidev5.1 and what it calls
          mikemoy

          Something else is weird as well. If you lower the speed to low then it all of a sudden jumps off the rails to some very high freq. At the time i did not measure this, but saw it on the scope.

          • 2. Re: Sources for /dev/spidev5.1 and what it calls
            KurtE

            Sounds interesting, wonder if it can be used to our advantage.

             

            I still can not answer any of the questions I asked in the first post..

             

            So I am trying to better understand the system, so I can hopefully help myself.

             

            So this weekend I purchased the book: Amazon.com: Embedded Linux Development with Yocto Project eBook: Otavio Salvador, Daiane Angolini: Kindle Store

            It obviously won't in itself answer the above questions, but hopefully it will help me to locate the appropriate files and show me ways to try out my own mods...

            • 3. Re: Sources for /dev/spidev5.1 and what it calls
              KurtE

              I may be barking up some wrong trees, but my guess is after my bitbake, the main code associated with SPI is in the directory:

              /home/kurt/edison-src/build/tmp/work/edison-poky-linux/linux-yocto/3.10.17+gitAUTOINC+6ad20f049a_c03195ed6e-r0/linux/drivers/spi)

               

              There are a couple of driver files I think are involved:

              spidev.c - which is what is handling our calls.

              intel_mod_ssp_spi.c - Which I think spidev is calling off to for at least some stuff.

              if ((sspc->quirks & QUIRKS_SPI_SLAVE_CLOCK_MODE) == 0) {

               

              clk_div = ssp_get_clk_div(sspc, spi->max_speed_hz);

               

              chip->cr0 |= (clk_div & 0xFFF) << 8;

               

              spi->max_speed_hz = ssp_get_speed(sspc, clk_div);

               

              chip->speed_hz = spi->max_speed_hz;

               

              dev_dbg(&spi->dev, "spi->max_speed_hz:%d clk_div:%x cr0:%x",

               

              spi->max_speed_hz, clk_div, chip->cr0);

                  }

               

               

               

              And if you look at the two functions:

              static unsigned int ssp_get_clk_div(struct ssp_drv_context *sspc, int speed)

              {

                  /* The clock divider shall stay between 3 and 4095 as specified in TRM. */

                  if (sspc->quirks & QUIRKS_PLATFORM_MRFL)

                      return clamp(25000000 / speed - 1, 3, 4095);

                  else

                      return clamp(100000000 / speed - 1, 3, 4095);

              }

               

               

              static int ssp_get_speed(struct ssp_drv_context *sspc, int clk_div)

              {

                  if (sspc->quirks & QUIRKS_PLATFORM_MRFL)

                      return 25000000 / (clk_div + 1);

                  else

                      return 100000000 / (clk_div + 1);

              }

               

              Sorry about formating above, need to figure out how to properly paste code in...

              But looking at these two functions: if I pass in 8000000 for speed, the first function, will divide 25000000/8000000 -1 = 2, but then clamp it up to a 3.  Then it calls off to the second function with the 3 which sets the max speed to 25000000/4 = 6.25mhz which is what we are seeing...

               

              Edit: I believe that the above code is generated as part of the build from the file:

              edison-src/device-software/meta-edison/recipes-kernel/linux/files/upstream_to_edison.patch

              • 4. Re: Sources for /dev/spidev5.1 and what it calls
                Intel_Alvarado

                Hi KurtE,

                We will investigate on this and let you know when we’ve found some useful information.

                Regards

                Sergio

                • 5. Re: Sources for /dev/spidev5.1 and what it calls
                  KurtE

                  Thanks,

                   

                  FYI - I tried the hack to change:

                    if (sspc->quirks & QUIRKS_PLATFORM_MRFL)

                          return clamp(25000000 / speed - 1, 3, 4095)

                  to:

                    if (sspc->quirks & QUIRKS_PLATFORM_MRFL)

                          return clamp(25000000 / speed - 1, 2, 4095);

                   

                  And build and did the flashall.sh

                   

                  And when I tried my program to set it to 8mhz,  It faulted:

                  root@Edison:/media/sdcard/root/Raspberry_Pi/testAdafruit_ILI9341C# ./graphictest

                  ILI9341 Test!

                  Above spi bus countSegmentation fault

                   

                  So I am rebuilding reflashing now with build minus this...

                   

                  Side note: the linux instructions for flashing an image: Flashing Edison (wired) - Linux

                  should be updated to say you need to do sudo ./flashall.sh

                  without running as sudo, the script completes, does not show any errors, but did not really do anything...

                   

                  Kurt

                  • 6. Re: Sources for /dev/spidev5.1 and what it calls
                    KurtE

                    Looking into the gap between bytes output, my guess so far is again in the file intel_mid_ssp_spi.c, I am pretty sure that for some reason DMA transfers is not enabled, so we go to the function poll_transfer to do the IO.

                     

                    I am not 100% sure here, but I am pretty sure that the CPU is Tangier, that is:

                        intel_mid_identify_cpu will return INTEL_MID_CHIP_TANGIER

                     

                    I am guessing that: intel_mid_identify_sim() will return INTEL_MID_CPU_SIMULATION_NONE.

                     

                    So I think the Intel_mid_ssp_spi_probe will set: ssp_timing_wr = 1

                     

                    so in the function poll_transfer,  for each byte transferred, it will loop 100 times with a udelay(10) unless some value (read_sFIFDL(sspc->ioaddr)) &0xffff, for some issue with debug uart on A0 stepping...

                     

                    Wonder if this is still needed.  Also wonder why done on all SPI devices instead of a specific one...  Maybe need to play...

                    • 7. Re: Sources for /dev/spidev5.1 and what it calls
                      KurtE

                      May have been barking up wrong tree here . I tried putting a hack in when the root->bus_num == 5 don't do the wait.  Built system, installed, and it looked like very little gap between bytes. But then I noticed my spi buss speed was something like 4K, I changed it back to 8K in the code, which again currently limited to 6.25k and then reran the code and the gaps are back.  I also noticed that the run times for the different tests are not much different. So I am now guessing the system is somehow limiting it.  Maybe it is simply the propagation time, from when I put a byte out on the TX until the response comes back on the RX and then we put the next byte out...

                       

                      Wonder if there is any TX/RX buffer you can make use of here.  That is, can you queue up more than one TX and as such the main poll_transfer loop would not to be updated to know the completion when we have transmitted and received the number of bytes specified....

                       

                      Edit: it looks like the TX/RX functions look like they support queuing multiple requests.  From the SR definitions, maybe 16 entry queue...

                      • 8. Re: Sources for /dev/spidev5.1 and what it calls
                        Intel_Alvarado

                        Hi KurtE,

                        Take a look at this post https://communities.intel.com/message/259055#259055 . Even though this is for Galileo I believe you can find it helpful.

                        Regards

                        Sergio