M4 SPI ChipSelect not toggleing

Problem:

I am trying to connect a SPI device on the Banana Pi M4. So far I could add a spidev to the device-tree and send bytes with a test program.

With a logic analyzer I could confirm that the clock signal is generated and MOSI is also working. Also the MISO pin seems to work (MISO connected to GND/3V3 reads back 0x00 or 0xFF as expected).

However, I cannot see any activity on the chip select pin (CS) and therefore the connected device is also not responding.

What could be the reasons that there is no CS signal? Is the Pinout described at the wiki accurate or could it be on anouther pin?

Thanks for any help in advance!


Steps to reproduce:

Base image

I used the rasbian image as a base.

Add SPI kernel driver

Compile the kernel with CONFIG_SPI_RTD139x enabled. Instructions (or use my kernel binary: uImage)

Replace the uImage in /boot/bananapi/bpi-m4/linux/

Enable spi and spidev in device tree

# goto boot dir
cd /boot/bananapi/bpi-m4/linux/
# decompile the device tree
dtc -I dtb -O dts -o rtd-1395-bananapi-m4.dts  rtd-1395-bananapi-m4.dtb

set spi status to “okay” and add spidev@0: {...};

	spi@9801BD00 {
		compatible = "Realtek,rtk-dw-apb-ssi";
		#address-cells = <0x1>;
		#size-cells = <0x0>;
		interrupt-parent = <0x7>;
		interrupts = <0x0 0x1b>;
		reg = <0x9801bd00 0x100 0x9801b300 0x18>;
		pinctrl-names = "default";
		pinctrl-0 = <0x2c>;
		num-chipselect = <0x1>;
		bus-num = <0x0>;
		clocks = <0x1d 0x3>;
		clock-frequency = <0xf424000>;
		resets = <0x1a 0x2>;
		status = "okay";

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

Compile device tree and reboot

dtc -I dts -O dtb -o rtd-1395-bananapi-m4.dtb  rtd-1395-bananapi-m4.dts
reboot

Now the SPI device should be available (ls /dev/spidev0.0).

Test program

# wget https://raw.githubusercontent.com/torvalds/linux/master/tools/spi/spidev_test.c
# gcc -o spidev_test spidev_test.c
# ./spidev_test -v -D /dev/spidev0.0
spi mode: 0x0
bits per word: 8
max speed: 500000 Hz (500 KHz)
TX | FF FF FF FF FF FF 40 00 00 00 00 95 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF F0 0D  |......@.........................|
RX | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF  |................................|

Just tested the chip select pin directly as GPIO.

I can toggle the GPIO as follows:

echo 20 > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio20/direction
echo "1" > /sys/class/gpio/gpio20/value
echo "0" > /sys/class/gpio/gpio20/value

This also shows up in the logic analyzer, so the wiring is correct.

The pin number for SPI in device tree also matches gpio_20:

    gspi_pins_0: gspi_pins_0 {
      realtek,pins = "gspi_loc",
      "gpio_18", 
      "gpio_19",                     
      "gpio_20",
      "gpio_31";
      realtek,function = "gspi_loc0";
    }; 

What else can cause the pin not to toggle? Could there be some other function blocking the pin for SPI usage?

One more test to make sure the CS is the real problem here:

If I provide the CS value manually, the communication with the device is also working.

# echo 20 > /sys/class/gpio/export
# echo "out" > /sys/class/gpio/gpio20/direction
# echo "0" > /sys/class/gpio/gpio20/value;./spidev_test -v -s 20000 -D /dev/spidev0.0 -i input.bin;echo "1" > /sys/class/gpio/gpio20/value
spi mode: 0x0
bits per word: 8
max speed: 20000 Hz (20 KHz)
TX | 03 0E 00 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  |...|
RX | FF FF 80 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  |...|

Any help to get the the chip select pin working or hint why it is not working would be appreciated.

Looks like somehow the pin is not initialized. For now I added gpio_request(20, "gpio20"); to the spi driver and recompiled the kernel.

@f0i, it took me days to get to where you are. I used the ubuntu 16.04 server version and I would like to document the many steps made to get the /dev/spidev0.0

I modified the local copy of the repo (because I didn’t have the time to figure out the elegant way to do it). @f0i, your insights were invaluable.

Building on previous steps:

  1. in local repo, add SPI kernel driver to linux-rtk/arch/arm64/configs/rtd139x_bpi_defconfig line 2537: in the section

Section: SPI Protocol Masters
CONFIG_SPI_RTD139x=y

**Bonus I2C - enable DS1307 **
line 4324: in the section

I2C RTC drivers
CONFIG_RTC_DRV_DS1307=y
CONFIG_RTC_DRV_DS1307_HWMON=y

  1. rebuild the kernel ./build_sh 3

  2. rebuild the u-boot image!! ./build_sh 2

  3. repackage the files: ./build_sh 6

  4. copy files to the sdcard as per documentation (using su) https://github.com/BPI-SINOVOIP/BPI-M2U-bsp/blob/420a1ad51515d63306df465b05f91c32b4711528/BPI-M2Ultra_Compiler_SOP.pdf

using su
tar -xvf BPI-BOOT-bpi-m4.tgz -C {boot partition usually p1}
tar -xvf 4.9.119-BPI-M4-Kernel-net.tgz -C {root partition usually p2}
tar -xvf 4.9.119-BPI-M4-Kernel.tgz -C {root partition usually p2}

  1. modify the .dtb in /BOOT/bananapi/bpi-m4/linux/
    Make the changes suggested to the .dtb file to enable the spidev and I2C functionality.

spi@9801BD00 {
compatible = “Realtek,rtk-dw-apb-ssi”;
#address-cells = <0x1>;
#size-cells = <0x0>;
interrupt-parent = <0x7>;
interrupts = <0x0 0x1b>;
reg = <0x9801bd00 0x100 0x9801b300 0x18>;
pinctrl-names = “default”;
pinctrl-0 = <0x2c>;
num-chipselect = <0x1>;
bus-num = <0x0>;
clocks = <0x1d 0x3>;
clock-frequency = <0xf424000>;
resets = <0x1a 0x2>;
status = “okay”;
spidev@0 {
compatible = “spidev”;
status = “okay”;
reg = <0>;
spi-max-frequency = <1000000>;
};
};

I2c functionality:

i2c@0x98007C00 {
	compatible = "Realtek,rtk-i2c";
	reg = <0x98007c00 0x400>;
	interrupt-parent = <0x7>;
	interrupts = <0x1 0xb>;
	i2c-num = <0x1>;
	**status = "okay";**
	pinctrl-names = "default";
	pinctrl-0 = <0x2a>;
	#address-cells = <0x1>;
	#size-cells = <0x0>;
	clocks = <0xa 0xa>;
	resets = <0x8 0xc>;
};
  1. compile the .dtb file from the .dts file as suggested
  2. within /BOOT/bananapi/bpi-m4/linux/ verify uEnv.txt uses the .dtb created
1 Like

Greetings … After having to revisit these issues after a while, the most reliable solution is to use the build tools within a docker environment. Ensure to use the option to “configure the kernel”. Then select Realtek SPI and enable all I2C related built-in components in the kernel.

Build everything, then transfer the files to you image.