This is a cache of https://discuss.96boards.org/t/how-to-enable-spi-and-access-it-in-debian-os/341. It is a snapshot of the page at 2024-11-01T09:00:50.281+0000.
How to enable spi and access it in Debian os - DragonBoard410c - 96Boards Forum

How to enable spi and access it in Debian os

Hi i am using Debian version in DB410c, for my project i want to use spi to integrate my Mcp3008 with DB410c. when i use “dmesg|grep spi” command i am seeing something like “SPI FIFO in- … FIFO out-…”. I want to enable spi and access it for my project. please help me to sort it out.

Hi. You can refer to https://developer.qualcomm.com/qfile/28819/lm80-p0436-5_peripherals_programming_guide.pdf chapter 5 for all the info and references you need.

Hi, thank you for your reply. In that document they said to change kernel files, but i am unable to find those files in my DB410c. I am unable to find device tree in my Debian os. help me to find it out.
Thankyou

Follow the instructions here to set up a build environment for the kernel on your development machine and make the changes there:
http://builds.96boards.org/releases/dragonboard410c/linaro/debian/latest/

As for the topic at hand, I’m having issues with SPI as well. I’ve set up the development environment, built the kernel, modules, etc., built and flashed the boot image, and everything seems fine with that. As for SPI, I added a section in arch/arm64/boot/dts/qcom/msm8916.dtsi under blsp_spi5 for spidev:

spidev@0 {
compatible = "spidev";
spi-max-frequency = <50000000>;
reg = <0>;
};

and modified .config to build the spidev module. When I insert spidev on the 410c, it creates a device at /dev/spidev32764.0, and I get this output in syslog:

Jul  3 18:59:14 linaro-developer kernel: [  778.639195] spidev spi32764.0: buggy DT: spidev listed directly in DT
Jul  3 18:59:14 linaro-developer kernel: [  778.639270] ------------[ cut here ]------------
Jul  3 18:59:14 linaro-developer kernel: [  778.646197] WARNING: CPU: 2 PID: 2181 at drivers/spi/spidev.c:719 spidev_probe+0x1c0/0x238 [spidev]()
Jul  3 18:59:14 linaro-developer kernel: [  778.649338] Modules linked in: spidev(+) spi_qup wcn36xx wcn36xx_platform [last unloaded: spi_qup]
Jul  3 18:59:14 linaro-developer kernel: [  778.667314] CPU: 3 PID: 2181 Comm: insmod Tainted: G        W       4.2.4-linaro-lt-qcom #3
Jul  3 18:59:14 linaro-developer kernel: [  778.667394] Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
Jul  3 18:59:14 linaro-developer kernel: [  778.675656] Call trace:
Jul  3 18:59:14 linaro-developer kernel: [  778.682622] [<ffffffc000089dd8>] dump_backtrace+0x0/0x148
Jul  3 18:59:14 linaro-developer kernel: [  778.684681] [<ffffffc000089f30>] show_stack+0x10/0x20
Jul  3 18:59:14 linaro-developer kernel: [  778.690349] [<ffffffc000909b5c>] dump_stack+0x88/0xc8
Jul  3 18:59:14 linaro-developer kernel: [  778.695269] [<ffffffc0000b91d4>] warn_slowpath_common+0x94/0xd0
Jul  3 18:59:14 linaro-developer kernel: [  778.700390] [<ffffffc0000b92b4>] warn_slowpath_null+0x14/0x20
Jul  3 18:59:14 linaro-developer kernel: [  778.706053] [<ffffffbffc04332c>] spidev_probe+0x1bc/0x238 [spidev]
Jul  3 18:59:14 linaro-developer kernel: [  778.712023] [<ffffffc0005426e4>] spi_drv_probe+0x64/0xa8
Jul  3 18:59:14 linaro-developer kernel: [  778.718015] [<ffffffc0004e6018>] driver_probe_device+0x1f0/0x440
Jul  3 18:59:14 linaro-developer kernel: [  778.723585] [<ffffffc0004e6308>] __driver_attach+0xa0/0xa8
Jul  3 18:59:14 linaro-developer kernel: [  778.729466] [<ffffffc0004e3dfc>] bus_for_each_dev+0x5c/0xa0
Jul  3 18:59:14 linaro-developer kernel: [  778.734847] [<ffffffc0004e5814>] driver_attach+0x1c/0x28
Jul  3 18:59:14 linaro-developer kernel: [  778.740328] [<ffffffc0004e539c>] bus_add_driver+0x204/0x290
Jul  3 18:59:14 linaro-developer kernel: [  778.745785] [<ffffffc0004e6b0c>] driver_register+0x5c/0x120
Jul  3 18:59:14 linaro-developer kernel: [  778.751163] [<ffffffc000542624>] spi_register_driver+0x54/0x60
Jul  3 18:59:14 linaro-developer kernel: [  778.756670] [<ffffffbffc04707c>] spidev_init+0x7c/0xe8 [spidev]
Jul  3 18:59:14 linaro-developer kernel: [  778.762639] [<ffffffc0000828e4>] do_one_initcall+0xcc/0x1e0
Jul  3 18:59:14 linaro-developer kernel: [  778.768362] [<ffffffc000908f78>] do_init_module+0x58/0x1c8
Jul  3 18:59:14 linaro-developer kernel: [  778.773996] [<ffffffc00013d9dc>] load_module+0x1a84/0x2030
Jul  3 18:59:14 linaro-developer kernel: [  778.779467] [<ffffffc00013e214>] SyS_finit_module+0xbc/0xf0
Jul  3 18:59:14 linaro-developer kernel: [  778.785002] ---[ end trace 6d3f103e0e938b96 ]---

Is that normal or indicative of a problem? Continuing on, I tried to run spidev_test from here:
https://www.kernel.org/doc/Documentation/spi/spidev_test.c

But it throws an error:

Jul  3 18:59:23 linaro-developer kernel: [  188.221048] spi_qup 78b9000.spi: OUTPUT_OVER_RUN
Jul  3 18:59:23 linaro-developer kernel: [  188.225798] spidev spi32766.0: SPI transfer failed: -5
Jul  3 18:59:23 linaro-developer kernel: [  188.228530] spi_master spi32766: failed to transfer one message from queue

Where should I start looking to fix the problem? msm8916.dtsi? spidev? spidev_test?

If anybody has a complete, working example of SPI on the 410c I would love to see it, it’s a lot easier to modify a working example to suit your needs than to hammer away at files hoping something will get it working.

Hi,
Thankyou for your help. i tried steps to build kernel from the link give below http://builds.96boards.org/releases/dragonboard410c/linaro/debian/latest/

But, when i try to rum “make image” step i am getting error. Also i tried to edit kernel for spi enable by following steps in “Peripherals and programming tutorial.pdf” given by 96Boards, i am getting msm8916.dtsi file but other than that pincontrol and clock files. where can i get detailed tutorial to do this.

"/bin/sh: 1: /home/…/gcc-linaro-4.9-2014.11-x86_64_aarch64-linux-gnu/aarch64-linux-gnu-gcc: not found
make[1]: *** [kernel/bounds.s] Error 127
make: *** [prepare0] Error 2

This is what i am getting when try to run “make -j4 Image KERNELRELEASE=4.2.0-linaro-lt-qcom” in my host pc.How to resolve this

You either don’t have a cross-compiler installed, or you used the wrong path to it when you set your CROSS_COMPILE environment variable.

Anybody have any input on getting SPI running on the 410c? Has anybody got this working yet?

I too have tried to get SPI running for the last couple of days. I built a new kernel based on the Debian 15.11 release. I added the spidev under blsp5 as suicidaleggroll has suggested above. When in install and start the kernel I get a console error message as I am booting:
[ 6.295037] Error: Driver 'spi_qup' is already registered, aborting…
when I look in /dev there is no spidev. I had expected to find /dev/spi32766.0, but no luck. I did find the file /sys/bus/spi/devices/spi32766 so I think I am on the right track, but it is not working yet.

Next I installed libsoc, (sudo apt-get install libsoc-dev) and I attempted to compile the sliding-rheostat program that comes with the linker board http://learn.linksprite.com/96-board/sliding-rheostat/, but the first thing I get is a compile error at the line
spi *spi_dev = libsoc_spi_init(32766,0);
since libsoc expects the spi device number to be a uint8_t, which of course is too small to hold this larger device number. I then installed libsoc (git https://github.com/jackmitch/libsoc) and changed the definition to uint16_t. After rebuilding and installing the modified libsoc the test program compiles cleanly, but libsoc fails with an error message:
libsoc-spi-debug: /dev/spidev254.0 not a valid device (spidev254.0, libsoc_spi_init)

Any hints on what I should try next?

One other tid-bit of information. Each time I run the rheostat program I get a console message:

[ 1948.551869] spi_test[2030]: unhandled level 2 translation fault (11) at 0x00000004, esr 0x92000006
[ 1948.551902] pgd = ffffffc0353fa000
[ 1948.560477] [00000004] *pgd=00000000b514f003, *pud=00000000b514f003, *pmd=0000000000000000
[ 1948.571164]
[ 1948.571433] CPU: 2 PID: 2030 Comm: spi_test Not tainted 4.2.4-linaro-lt-qcom #2
[ 1948.572996] Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
[ 1948.581056] task: ffffffc02663d300 ti: ffffffc028a90000 task.ti: ffffffc028a90000
[ 1948.586975] PC is at 0x400e00
[ 1948.595165] LR is at 0x400df8
[ 1948.597298] pc : [<0000000000400e00>] lr : [<0000000000400df8>] pstate: 60000000
[ 1948.600936] sp : 0000007fec6b1f30
[ 1948.607715] x29: 0000007fec6b1f30 x28: 0000000000000000
[ 1948.616042] x27: 0000000000000000 x26: 0000000000000000 [ 1948.619822] x25: 0000000000000000 x24: 0000000000000000
[ 1948.619829] x23: 0000000000000000 x22: 0000000000000000
[ 1948.619837] x21: 0000000000400c50 x20: 0000000000000000
[ 1948.619844] x19: 0000000000000000 x18: 0000007fec6b1c20
[ 1948.619852] x17: 0000007f86919128 x16: 0000007f868302cc
[ 1948.619859] x15: 0000007f868fd588 x14: ffffffffffff0000
[ 1948.619867] x13: ffffffffffffffff x12: 0000000000000038
[ 1948.619874] x11: 000000000000000f x10: 00000000ffffffff
[ 1948.619881] x9 : ff73686d685e686f x8 : 000000002b4a2030
[ 1948.619888] x7 : 0000007fec6b1eb8 x6 : 0000000000000000
[ 1948.619895] x5 : 00000000ffffffff x4 : 0000007f868fb560
[ 1948.619902] x3 : 0000000000000000 x2 : 2f9662b832055200
[ 1948.619909] x1 : 0000000000000000 x0 : 0000000000000000
[ 1948.619915]

Hello there,
The bus number allocation logic gives bus numbers starting from (1<<15 -1) if its not explicitly set in DT, so you get that huge number.
However the correct fix is to add aliases to the spi device node to get the correct bus number matching schematics. Here is patch you could try : [PATCH] arm64: dts: apq8016-sbc: Add aliases to spi device.

This patch along with spidev node under blsp_spi5 you would see spidev.0.0
and spitest works for me.

root@linaro-developer:~# spitest -D /dev/spidev.0.0
spi mode: 0x0
bits per word: 8
max speed: 500000 Hz (500 KHz)

00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00 00 00 00 00
00 00

Regarding the big warning when we add spidev, is a genuine warning. This is because spidev is not really a device and it is not expected it exisit in device tree file. spidev is a detail of how linux
controls a device rather than a description of the hardware.

Thanks,
srini

Thanks Srini.

I added your patch, and the change suggested by Suicideeggroll at the beginning of this thread. I now have a /dev/spidev0.0 file. I then used libsoc to access the device and it is working great. The code and peripherals I am using are part of the Linker 96Boards kit from LinkSprite and the ‘sample’ code for the Rheostat program only needed one minor change, I changed the constant 32766 to 0. http://learn.linksprite.com/96-board/sliding-rheostat/

Thanks

Ugh - so apparently my problem this whole time has been that the default message in spidev_test.c is too big for the ioctl interface on the dragonboard 410c’s implementation of spidev. It looks like the limit is 31 bytes (31 ok, 32 not ok), and the default spidev_test.c message is, you guessed it, 32 bytes. Anything 31 and under works fine, but 32 throws a buffer overrun error. I didn’t suspect this since that same code works fine on spidev on a Raspberry Pi, oh well.

Thanks for the patch to force the spi interface to spidev0.0, that helps. I kept getting a different bus number every time I loaded the module before I added that alias.

So it looks like both spidev and spi-qup are designed to handle at least 4096 bytes per transfer, but spi-qup throws a buffer overrun error with anything more than 31 bytes. Is this a bug in spi-qup or elsewhere?

Apparently the problem is worse than I thought. While it will allow a single transfer up to 31 bytes, back-to-back transfers still cause it to fail unless the size is reduced to 16 bytes or smaller. Add in a ~70 ns delay between bytes and a ~78 uS delay between transfers, and this drops the total throughput to a measly 200 kBps (1.6 Mbps) when running with a 50 MHz spi clock.

I tested on an RPi2, and while it has a longer delay between transfers of ~140 uS and a slightly slower clock speed (41.67 MHz), it’s able to do 4096 bytes per transfer and sustain a throughput of a hair over 4 MBps (32 Mbps), about 20x faster than the dragonboard, with a significantly slower processor.

Something is definitely wrong with spi-qup on the current debian release for the dragonboard. It shouldn’t be throwing buffer overflow faults when sending it more than 16 bytes per transfer.

Any idea what could be causing this?

Hi suicidaleggroll,
Am happy to help you debug this issue, but to do that I would like few details from you to reproduce the same on my side.
1> exact hardware setup details.
2> software instructions to reproduce the issue.

On the other note, Recently I did try to hook up and ENC28J60 spi ethernet module with level shifters to DB410C and I could test it successfully, here is the log: http://paste.ubuntu.com/14680065/
and here are the kernel sources with patches https://git.linaro.org/people/srinivas.kandagatla/linux.git/shortlog/refs/heads/spi-debian-qcom-dragonboard410c-15.11 that I used for testing.

thanks,
srini

Sure thing.

The hardware is nothing special, just the 410c with spi on the LS expansion connector hooked up to a logic analyzer for testing. Eventually it will be attached to a custom CPLD/SRAM FIFO that I designed and built, which will buffer data from a high speed A/D so the 410c can pull it off when it gets around to it (getting around the need for a RTOS on the 410c, all I need is an average transfer rate > 3 MBps to keep up and the FIFO will buffer through any hiccups or delays).

For the RPi, just load the latest Raspbian image and use raspi-config to turn on spi, then reboot.

For the 410c, the build system is on OpenSUSE Tumbleweed, using the gcc-linaro-4.9-2014.11-x86_64_aarch64-linux-gnu compiler from here:
https://releases.linaro.org/14.11/components/toolchain/binaries/aarch64-linux-gnu/

The build process follows this guide:
http://builds.96boards.org/releases/dragonboard410c/linaro/debian/15.11/

With the following modifications:
in .config:
CONFIG_SPI_SPIDEV=m

in arch/arm64/boot/dts/qcom/msm8916.dtsi, in blsp_spi5 (line 1279):

spidev@0 {
   compatible = &quot;spidev&quot;;
   spi-max-frequency = &lt;50000000&gt;;
   reg = &lt;0&gt;;
};

in arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi, in aliases (line 29):

spi0    = &amp;blsp_spi5;
spi1    = &amp;blsp_spi3;

Once the boot image is built and loaded with fastboot, and the 410c is started, copy over spidev.ko and insert it.

Then build this code:
http://thesuicidaleggroll.com/hosting/drain.c

It started out as this:
http://free-electrons.com/kerneldoc/latest/spi/spidev_test.c
and I modified it slightly to just send the numbers 0-255 over and over again in configurable batch sizes. Use the “size” variable on line 294 to control the batch size. If it fails, it will also print out the number of batches it was able to successfully send before the failure.

On the RPi, any size between 1-4096 works fine. With it set to 4096, the RPi clocks out the 4096 bytes continuously (no gap between bytes) at a rate of 41.67 MHz, plus a gap of ~140 uS between batches. This means it takes ~925 uS per 4096 bytes, which is a rate of ~4.2 MBps. When it’s set to 4097 or higher, it throws the following error:
can’t send spi message: Message too long

which is the expected behavior.

On the 410c, any size between 1-16 works fine. With it set to 16, the 410c clocks out the 16 bytes at 50 MHz, with a gap of 70 nS between bytes, and a gap of ~78 uS between batches. This means it takes ~82 uS per 16 bytes, which is a rate of ~200 kBps. By my estimate, I need to be able to set the size to at least 650 in order to keep up with my desired data rate (a hair under 3 MBps). With it set to 4097, it throws the following error:
can’t send spi message: Message too long

which is the expected behavior. With any size between 17-31, it works initially but crashes within a few seconds. Any size between 32-4096 crashes it immediately. When it crashes, the output of the code is:
can’t send spi message: Input/output error

The output on the serial console is:
[51953.068850] spi_qup 78b9000.spi: OUTPUT_OVER_RUN
[51953.068972] spidev spi0.0: SPI transfer failed: -5
[51953.072568] spi_master spi0: failed to transfer one message from queue

And the output in /var/log/messages is:
Jul 4 09:12:08 linaro-developer kernel: [51953.068850] spi_qup 78b9000.spi: OUTPUT_OVER_RUN

When it crashes, the spidev and spi-qup kernel modules need to be removed and re-inserted (or the system rebooted) before SPI will work again.

@ljking Did you also have to change GPIO_CS 18 in the sample program to something else? I see no such number in /sys/class/gpio, only 0, 472, 476 and 480, so not sure which one to use instead.

Hi @vchong. No I did not change GPIO_CS 18 in the sample program, that was working just fine. I did do one thing different, I did not install the libsoc package (sudo apt-get install libsoc-dev), instead I downloaded the libsoc source from https://github.com/jackmitch/libsoc and rebuilt it from scratch. The latest libsoc has patches specific to the 410c board and it may be doing GPIO number translation (I’m not sure). Let me know if this works for you (I think this is what I did).

	sudo apt-get update
	sudo apt-get upgrade
	sudo apt-get install autoconf automake libtool
        git clone https://github.com/jackmitch/libsoc.git
        cd libsoc
        ./autogen.sh
        ./configure --enable-board=dragonboard410c
        make
        sudo make install

@ljking Thanks! I’ve looked at the libsoc_gpio.conf file for the db410c but see no 18 either. Can you please paste the content of your ls /sys/class/gpio?

My power-up /sys/class/gpio looks exactly the same as yours. There is no gpio18.

GPIO_18 is correct gpio. If you look at the 410c schematics (http://linaro.co/db410c-schematics) (page 5) you will see that GPIO_18 is the SPI chip select and it goes to the low-speed connector (page 29) at pin 12.

By default this SOC pin is not exported (same with most of the other gpios for that matter). What libsoc does is it first checks to see if the gpio has been exported, if it has not been exported (which is the case) then libsoc does an export by writing “18” to /sys/class/gpio/export (you can do this manually with echo). After the export you will find gpio18 in /sys/class/gpio. Finally you can drive the CS high or low by writing a “1” or “0” to /sys/class/gpio/gpio18/value (again you can do this manually with echo).

The libsoc GPIO config file only aliases GPIO_A through GPIO_L so that code written to one 96Boards SOC can be ported to another SOC. I suspect that there should be aliases added for things like the SPI chip select.

Full Disclosure: I am an employee of Qualcomm Canada, any opinions expressed in this or any other post may not reflect the opinions of my employer.