SPI on Dragon Board 410 not functional on LS Expansion Conector

Hi everybody,

I have SPI up and running, using spidev.ko and spidev_test.c, on HS Expansion Connector but not on LS Expansion Conector.

I use linux_android_board_support_package_vla.br_.1.2.4-01810-8x16.0-3.zip code to build Android system. I have recompiled it adding on kernel/arch/arm/boot/dts/qcom/msm8916.dtsi the node to spidev kernel module.

spi_0: spi@78b7000 { /* BLSP1 QUP3 */
	compatible = "qcom,spi-qup-v2";
            #address-cells = <1>;
            #size-cells = <0>;
            reg-names = "spi_physical", "spi_bam_physical";
            reg = <0x78b7000 0x600>,
                  <0x7884000 0x23000>;
            interrupt-names = "spi_irq", "spi_bam_irq";
            interrupts = <0 97 0>, <0 238 0>;
            spi-max-frequency = <50000000>;
            pinctrl-names = "spi_default", "spi_sleep";
            pinctrl-0 = <&spi0_default &spi0_cs0_active>;
	pinctrl-1 = <&spi0_sleep &spi0_cs0_sleep>;
	clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
		 <&clock_gcc clk_gcc_blsp1_qup3_spi_apps_clk>;
	clock-names = "iface_clk", "core_clk";
            qcom,infinite-mode = <0>;
	qcom,use-bam;
	qcom,use-pinctrl;
            qcom,ver-reg-exists;
            qcom,bam-consumer-pipe-index = <8>;
            qcom,bam-producer-pipe-index = <9>;
            qcom,master-id = <86>;

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

On kernel/arch/arm/boot/dts/qcom/msm8916-pinctrl.dtsi

	spi0_active {
		/* MOSI, MISO, CLK */
		qcom,pins = <&gp 8>, <&gp 9>, <&gp 11>;
		qcom,num-grp-pins = <3>;
		qcom,pin-func = <1>;
		label = "spi0-active";
		/* active state */
		spi0_default: spi0_default {
			drive-strength = <12>; /* 12 MA */
			bias-disable = <0>; /* No PULL */
		};
	};

	spi0_suspend {
		/* MOSI, MISO, CLK */
		qcom,pins = <&gp 8>, <&gp 9>, <&gp 11>;
		qcom,num-grp-pins = <3>;
		qcom,pin-func = <0>;
		label = "spi0-suspend";
		/* suspended state */
		spi0_sleep: spi0_sleep {
			drive-strength = <2>; /* 2 MA */
			bias-pull-down; /* pull down */
		};
	};
	spi0_cs0_active {
		/* CS */
		qcom,pins = <&gp 10>;
		qcom,num-grp-pins = <1>;
		qcom,pin-func = <1>;
		label = "spi0-cs0-active";
		spi0_cs0_active: cs0_active {
			drive-strength = <2>;
			bias-disable = <0>;
		};
	};


	spi0_cs0_suspend {
		/* CS */
		qcom,pins = <&gp 10>;
		qcom,num-grp-pins = <1>;
		qcom,pin-func = <0>;
		label = "spi0-cs0-suspend";
		spi0_cs0_sleep: cs0_sleep {
			drive-strength = <2>;
			bias-disable = <0>;
		};
	};

As It can be seen,
/* MOSI, MISO, CLK */
qcom,pins = <&gp 8>, <&gp 9>, <&gp 11>;

MOSI, MISO and CLK are located at HS Expansion board. After reflashing, everything goes fine in this scenario, I can see:

root@msm8916_64:/ # ls /dev | grep spi
spidev0.0

And running spidev_test y see the signal of CLK in the scope at pin9, connector J9 (HS Expansion Board).

My goal is to have this interface spidev0.0 on J8 (LS Expansion Connector), in orther to achieve this I have modified kernel/arch/arm/boot/dts/qcom/msm8916-pinctrl.dtsi, replacing the location of MOSI, MISO and CLK to:

                      /* MOSI, MISO, CLK */
                      qcom,pins = &lt;&amp;gp 16&gt;, &lt;&amp;gp 17&gt;, &lt;&amp;gp 19&gt;;

Everything else is not modified. I recompile & reflash boot image. I get again:

root@msm8916_64:/ # ls /dev | grep spi
spidev0.0

But, when try to run spidev_test, it fails with the following output:

root@msm8916_64:/ # ./spidev_test_00
spi mode: 0
bits per word: 8
max speed: 500000 Hz (500 KHz)
can’t send spi message: I/O error
Aborted

I have checked with the scope the new assigned pins and there is no activity on CLK line.

Am I missing anything if I just want to change the gpios used by a driver on this chip ? Is there any limitation on LS expansion connector for SPI ?

Any idea is more than welcome :slight_smile:

Thanks,

Gerardo

Under the previous kernel we had the SPI up and running on the LS connector. See the discussion and the patches here. https://www.96boards.org/forums/topic/how-to-enable-spi-and-access-it-in-debian-os/. I haven’t re-tried SPI with the latest kernel release, but I thought that most of the changes would be in this kernel and it would work.

Hi Geraldo
I had time to test out SPI on the LS expansion connector today, using the latest release operating system for the board (Debian 66). I needed to make a few changes, first to the kernel configuration:

make menuconfig
    Select “Device Drivers” then &lt;Enter&gt;
    Select “SPI Support” followed by &lt;Enter&gt;
    Select “User mode SPI device driver support” Followed by ‘Y’.
    Back out of the menus with repeated &lt;esc&gt;&lt;esc&gt; and at the end select ‘Yes’ to save the changes.

then to the device tree. Edit the file

    arch/arm64/boot/dts/qcom/apq8016-sbc
under aliases add:

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

and under spi@78b9000 add:

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

After you rebuild the kernel and the device tree you should have the file

    /dev/spidev0.0

I was able to read the ADC on the linker board by running the code on this page http://learn.linksprite.com/96-board/sliding-rheostat/ although I did need to change the constant 32766 to 0.

Note: I only checked basic operation, not performance so I am not sure if the other performance patches mentioned in the tread mentioned above need to be installed or not.

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

Hi Geraldo

I also looked at your “changes” to the Android kernel, you are attempting use the same QUP and just remap the pins. The chipset contains multiple QUPs and each QUP has a dedicated set of pins, The QUP connected to the low speed connector uses pins 19,18,17,16 as you noted in your changes, however the correct QUP for the LS connector is not at location 78b7000 (BLSP1QUP3), it is at 78b9000 (BLSP1QUP5). I have not made changes to the Android kernel (yet), but I think you need to define a new spi1 interface to access to LS connector SPI interface.

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

Hello,

Thanks for the support. It works perfectly using the location 78b9000 (BLSP1QUP5) for spi. I do not know the constrains for mapping the QUPs to specific pins, where that info can be found ?

Thanks,

Gerardo

Hi Geraldo:

The place where I looked for it was on the schematics (you can find a link to the schematic here: https://www.96boards.org/products/ce/dragonboard410c/docs/) look at page 5/34). Additionally the information is in the processor device specification (link to the processor device specification is on the same page as the schematic), look at page 31/107.

A side note: in the Debian code base, the serial peripherals and names BLSP[1:6], and in the Android code base they are named BLSP1QUP[1:6], different naming for the same thing. Personally I prefer the Debian naming because it better matches the device specifications and schematics.

As a side note: once you realize that SPI, UART, and I2C ports all have the same hardware block behind them, you can see that with a few changes to the device tree you could convert UART0 to another SPI, or convert SPI1 to an I2C port. This gives more flexibility to the 410c hardware if you need a different mix of port types than are provided by default.

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

Hi. Is there some tutorial that is available which explains how to integrate SPI device with the DragonBoard? I know there is a nice video for I2C. It will be great if someone could do write up instructions on how to do it for SPI.

Hi,

@ljking: I am observing a weird behavior on SPI signals on the scope. When the spidev_test application do a transaction.

ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);

I see that CS signal is set low and after around 8 ms the transaction is done (CLK toggles). This is too long time from CS low until CLK toggles, so I think that there is something wrong on this regard.

I am using spidev as kernel driver binding to SPI_0 (BLSP1 QUP 4 spi@78b9000).

Have you observed same behavior ? I assume that spidev.ko is not the routing cause of the issue so maybe something in the lower level driver …

Thanks in advance,

Gerardo

Hi @mike123

There is some sample code for a spidev in the Linker Kit tutorials.

Hi @GerTola

Keep in mind I am running on the Debian kernel, not the Android kernel so my results are different than what you are seeing.

To be honest, I had only looked at “functionality” of the SPI interface, as long as I could read the ADC that is on the Linker board I was happy. I had not looked at “performance”. Today I connected a scope to the SPI lines, and I see that transactions (the chip select time) take a random amount of time between about 400us up to 1,000us (typically 500us on an lightly loaded system), I am transferring 3 bytes at 1MHz (about 30us). I did things slightly differently from you I built the spidev into the kernel, I did not make it a module. I am also using libsoc to do the transfers. libsoc activates the CS as a GPIO in the first call, then it reads the three bytes, then it deactivates the CS. While the performance is not stellar, it as about what I would expect.

@suicidaleggroll has done quite a bit of work on SPI performance and he seems to be happy with it after applying the patches listed in this post https://www.96boards.org/forums/topic/how-to-enable-spi-and-access-it-in-debian-os/, but again this is Debian, not Android.

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

@GerTola Did you perhaps add debugging statements into your code that could affect the timing of the signals?

hi,

@vchong The code is basically calling:

ret = ioctl(fd, SPI_IOC_MESSAGE(1), &amp;tr);

every 5ms. After calling ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr), CS is properly set low and the start of the transaction is done 8 ms after CS is set low. So, there is a delay clearly, but is not because of the program running on User Space, It cause of the delay might come from:

1.- spidev, kernel module, something that I doubt as It has been successfully tested on other platforms.
2.- spi-qup, low level driver. I guess It could be the root cause.

@ljking: After reading https://www.96boards.org/forums/topic/how-to-enable-spi-and-access-it-in-debian-os/ , I think that the patches that have been aplied for Debian should be applied on Android code base. I have tried to do so, but the driver files are different on Android from Debian(e.g. on debian is spi-qup.c and on Android spi_qsd.c) , and I can not find some of the patches, like:

git://git.kernel.org/pub/scm/linux/kernel/git/agross/linux.git
branch: spi-wip

8ec8b82 spi: qup: Fix block mode to work correctly
807582a spi: qup: Use correct check for DMA prep return
767532d spi: qup: Wait for QUP to complete
2c438ae spi: qup: Fix transaction done signaling

Apart from execute it from shell, I have launch it as a service after boot (including it on init.rc), and what I observe in this scenario is that during few seconds there is transaction after 20us of CS is set low, so the desired behavior but after few seconds it crashes I lost adb connection and reboot of the board is needed to have it functional.

Before continuing with the investigation I would like to know if the patches applied on Debian code are going to be ported on Android.

Thanks in advance,

Gerardo

Hi

I’m also having some troubles to make it work and am trying to make SPI0(LS) to work on Android.
Are there any news about these issues? It would be highly appreciated if someone who has experience with SPI and Android could comment.
By the way, I’m using “Android Board Support Package vLA.BR.1.2.4-01810-8x16.0-3”

Thanks,
Mike

Hi,

after made change in the device tree to enable spi on it, i want rebuild the kernel to flash the changes on the board.
To do that i executed below command on android source directory.
source build/envsetup.sh;
BOARD_NAME=msm8916
lunch “${BOARD_NAME}-userdebug”

I am getting below error when I do make bootimage -j16

PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=5.1.1
TARGET_PRODUCT=msm8916
TARGET_BUILD_VARIANT=userdebug
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a-neon
TARGET_CPU_VARIANT=generic
TARGET_2ND_ARCH=
TARGET_2ND_ARCH_VARIANT=
TARGET_2ND_CPU_VARIANT=
HOST_ARCH=x86_64
HOST_OS=linux
HOST_OS_EXTRA=Linux-3.19.0-25-generic-x86_64-with-Ubuntu-14.04-trusty
HOST_BUILD_TYPE=release
BUILD_ID=LMY47V
OUT_DIR=out

build/core/dex_preopt.mk:47: *** target pattern contains no `%’. Stop.

make failed to build some targets (2 seconds)

Please can anyone suggest me how to fix this problem.

Hi,

I fixed it by changing from BOARD_NAME=msm8916 to BOARD_NAME=msm8916_64

Thank you.

Hi Gerardo,

I followed your post to change msm8916.dtsi, adding spidev under spi_0. I have also made spidev built-in to the kernel. But when boot the android, I cannot find /dev/spidevX.X

What am I missing?

Thanks,
G

===========================

spidev@0 {
compatible = “spidev”;
reg = <0>;
spi-max-frequency = <1000000>;
};

Hi gossiper,

you found what you missied?
i am also facing this issue spidev is not enabled on LS expander android image.
I changed msm8916.dtsi and msm8916-pinctrl.dtsi according to the post and provided peripheral guide.
is any thing i am missing ?
changes made in msm8916.dtsi
--------------------------------:
aliases{

spi2 = &spi_2;

};
spi_2: spi@78b9000{ /*BLSP1 -QUP4 core
compatible = “qcom,spi-qup-v2”;
reg-names =“spi_physical”;
reg = <0x78b9000 0x600>,
<0x7884000 0x23000>;
interrupts = <0 99 0>;
spi-max-frequency = <25000000>;
#address-cells = <1>;
#size-cells = <0>;
clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
<&clock_gcc clk_gcc_blsp1_qup5_spi_apps_clk>;
clock-names = “iface_clk”, “core_clk”;
qcom,infinite-mode = <0>;
qcom,gpio-mosi = <&msm_gpio 16 0>; //this are needed here or not??
qcom,gpio-miso = <&msm_gpio 17 0>;
qcom,gpio-cs0 = <&msm_gpio 18 0>;
qcom,gpio-clk = <&msm_gpio 19 0>;
qcom,master-id = <86>;
spidev@0 {
compatible = “spidev”;
reg = <0>;
spi-max-frequency = <25000000>;
};
};
changes made in msm8916-pinctrl.dtsi:

these are actually there are on my kernel source msm8916-pinctrl.dtsi file
spi2_active {
/* MOSI, MISO, CLK /
qcom,pins = <&gp 16>, <&gp 17>, <&gp 19>;
qcom,num-grp-pins = <3>;
qcom,pin-func = <1>;
label = “spi2-active”;
/
active state /
spi2_default: default {
drive-strength = <12>; /
12 MA /
bias-disable = <0>; /
No PULL /
};
};
spi2_suspend {
/
MOSI, MISO, CLK /
qcom,pins = <&gp 16>, <&gp 17>, <&gp 19>;
qcom,num-grp-pins = <3>;
qcom,pin-func = <0>;
label = “spi2-suspend”;
/
suspended state /
spi2_sleep: sleep {
drive-strength = <2>; /
2 MA /
bias-pull-down; /
pull down /
};
};
spi2_cs2_active {
/
CS /
qcom,pins = <&gp 18>;
qcom,num-grp-pins = <1>;
qcom,pin-func = <1>;
label = “spi2-cs0-active”;
spi2_cs2_active: cs2_active {
drive-strength = <2>;
bias-disable = <0>;
};
};
spi2_cs2_suspend {
/
CS */
qcom,pins = <&gp 18>;
qcom,num-grp-pins = <1>;
qcom,pin-func = <0>;
label = “spi2-cs0-suspend”;
spi2_cs2_sleep: cs2_sleep {
drive-strength = <2>;
bias-disable = <0>;
};
};

Please any one tell me what iam missing to enable spidev (need to see spidev2.0 in /dev/ directory)on 410 dragon board.