Jump to content

Solved: Banana Pro (A20) SPI not working with mainline kernel (4.9.12)


Recommended Posts

Posted (edited)

Hey there,

I am having trouble with SPI on my Banana Pro. I am trying to access the SPI interface via WiringPI (the Lemaker Banana Pro version). But whenever I try to access it, it tells me:

  1. Unable to open SPI device: No such file or directory

     


The message is correct, as there are no /dev/spi* files present. The question is: How do I get them?
(according to http://linux-sunxi.org/Linux_mainlining_effort#Status_Matrix it should be available since 3.15)

For the 3.4.x, one had to load modules (spidev, etc.) but this doesn't seem to work for 4.9.x. There is a 'spidev' module which loads fine (according to lsmod) but with no recognizable outcome. Is there anything special I have to load/enable/etc.? Unformtunately I didn't find anything usefull on the web regarding this topic. Which either means, it is working for everyone else or I do not know what to look for. :-(

Any help is appriciated!

This is my welcome string with OS and kernel version:

  1. Welcome to ARMBIAN 5.25 stable Debian GNU/Linux 8 (jessie) 4.9.12-sunxi  

     

PS: This is a cross-post from the Lemaker forum - no answer over there so far, however.

 

 

 

--------

 

Thanks to zador.blood.stained I was able to enable SPI/SPIDEV for the mainline kernel (4.10.). For people with the same problem: This post contains a working device tree blob file (.dtb) which needs to be put into /boot/dtb folder. Additionally, an overlays=bananapro needs to be added to /boot/armbianEnv.txt

Post containing compiled device tree blob

 

 

 

Edited by Mr_Blonde
Solved remark added
Posted

Thanks for your response!
 

I found this wiki entry regarding overlays: https://docs.armbian.com/User-Guide_Allwinner_overlays/

 

However, for the Banana Pro there is no nightly build and an update to the current development kernel (4.10) did not bring overlays with it. :-(

Does that mean I have to setup my own build environment? Since I am not familiar with overlays, device trees, etc. Wouldn't it be easier for me to "simply" configure the kernel with SPI support build in and compile it on the device instead of setting up a complete build environment (acknowledging that the build will take quit some time on the ARM board)?

Posted

I specifically said "modifications" because overlays require some work to apply on current stable builds.

You still can edit the DT manually (without recompiling the whole kernel or setting up a build environment), there were some posts here related to it. The trickiest part will be adding pinctrl configuration (by label or phandle), I'm not sure if it was described or documented here.

Posted

Thanks to your comments, I looked a bit further into this.

 

As a first step, I disassembled/decompiled the appropriate device tree blob:

 

dtc -I dtb -O dts /boot/dtb-4.10.0-sunxi/sun7i-a20-bananapro.dtb > sun7i-a20-bananapro.dts

 

Then I tried to figure out how to modify it in order to get SPI and SPIDEV to work. That's, however, where I got stuck. :-( I read http://linux-sunxi.org/SPIdev but couldn't make much out of it since it seems that the device tree entries are very specific for each board.

 

For me it seams that SPI0 is already enabled:

	soc@01c00000 {
		spi@01c05000 {
			compatible = "allwinner,sun4i-a10-spi";
			reg = <0x1c05000 0x1000>;
			interrupts = <0x0 0xa 0x4>;
			clocks = <0x2 0x14 0x20>;
			clock-names = "ahb", "mod";
			dmas = <0x1f 0x1 0x1b 0x1f 0x1 0x1a>;
			dma-names = "rx", "tx";
			status = "okay";
			#address-cells = <0x1>;
			#size-cells = <0x0>;
			pinctrl-names = "default";
			pinctrl-0 = <0x21 0x22 0x23>;
		};
	};

and a 

ls /sys/class/spi_master/spi32766/
device    of_node  power    statistics  subsystem  uevent

seems to confirm that there is "something". The neighboring spidev folder is empty, though.

 

There are pin definitions for the spi0 and chip select (+ for spi1) as well:

 

	soc@01c00000 {
		pinctrl@01c20800 {
			spi0@0 {
				allwinner,pins = "PI11", "PI12", "PI13";
				allwinner,function = "spi0";
				allwinner,drive = <0x0>;
				allwinner,pull = <0x0>;
				linux,phandle = <0x21>;
				phandle = <0x21>;
			};

			spi0_cs0@0 {
				allwinner,pins = "PI10";
				allwinner,function = "spi0";
				allwinner,drive = <0x0>;
				allwinner,pull = <0x0>;
				linux,phandle = <0x22>;
				phandle = <0x22>;
			};

			spi0_cs1@0 {
				allwinner,pins = "PI14";
				allwinner,function = "spi0";
				allwinner,drive = <0x0>;
				allwinner,pull = <0x0>;
				linux,phandle = <0x23>;
				phandle = <0x23>;
			};
		};
	};

 

What is missing is a mentioning of spidev, however. So my guess is that I have to add it somewhere. The question is how and where. The two examples on http://linux-sunxi.org/SPIdev do not shed much light on this - at least for me. :-( 

 

Has someone already done it for the Banana Pro (A20) boards? In case not, is there a more generic description out there on how to configure/write the device tree?

 

 

Furthermore: What is next after adding spidev and compiling the device tree? Is having an entry in armbianEnv.txt such as:

overlays=bananapro

enough?

Posted
34 minutes ago, Mr_Blonde said:

The neighboring spidev folder is empty, though.

You have to add spidev child node to the controller node

		spi@01c05000 {
			compatible = "allwinner,sun4i-a10-spi";
			reg = <0x1c05000 0x1000>;
			interrupts = <0x0 0xa 0x4>;
			clocks = <0x2 0x14 0x20>;
			clock-names = "ahb", "mod";
			dmas = <0x1f 0x1 0x1b 0x1f 0x1 0x1a>;
			dma-names = "rx", "tx";
			status = "okay";
			#address-cells = <0x1>;
			#size-cells = <0x0>;
			pinctrl-names = "default";
			pinctrl-0 = <0x21 0x22 0x23>;
              
			spidev@0 {
				compatible = "spidev";
				status = "okay";
				reg = <0>; /* Chip select 0 */
				spi-max-frequency = <1000000>;
			};
		};

In the future it will be solved with DT overlays, but for now it's not implemented on the stable images.

Posted

It worked!  :-)

 

Thank you very much for your help! Attached are the .dts and compiled .dtb files for reference.

 

I aslo added an alias in order to have proper /dev/spidev0.0 instead of an /dev/spi32755.0. Here is the corresponding .dts snipped:

 

	aliases {
		spi0 = "/soc@01c00000/spi@01c05000";
	};

 

 

 

There is one strange thing though. I am using WiringPi on the device (the version from Lemaker) and on top a Java program with Pi4J library (which uses WiringPi to access the GPIOs).

To give you some background: My program is getting some information and is then updating an eInk display via the SPI interface. In order to update the display I am reading some status bytes from it and sending a complete new image for each update. Before refreshing the display I am querying the display's internal temperature sensor. Sending the command to query the sensor is the very first byte my program is transmitting on the SPI bus. With the old legacy kernel, the program worked without any problems. Now, however, I get a java.io.IOException: Failed to write data to SPI channel: 0 exception. Subsequent writes on the SPI bus work nevertheless (and the display is refreshed properly). In order to track down the problem, I tried to get the eInk display info before retrieving the temperature (which is done by sending another command byte and waiting for the response). The result: Now, retrieving the display information causes the before-mentioned exception and reading the temperature sensor works.

 

As an executive summary: I now have the problem that the very first write to the SPI bus fails with java.io.IOException: Failed to write data to SPI channel: 0 exception whenever I execute my program. All subsequent writes (and inherent reads on the bus) work like a charm. The weird thing is that its not only the very first bus access after a reboot but always when I execute my program. With the legacy kernel 3.4.x my code worked without this issue.

 

Its a 'minor' issue but maybe some else has come across the same issue and can shed some light on this.

 

Java code SPI init (via Pi4J library)

PlatformManager.setPlatform(Platform.BANANAPRO);
			
spi = SpiFactory.getInstance(SpiChannel.CS0,
	1000000, // default spi speed 1 MHz
	SpiMode.MODE_0); // default spi mode 0

 

sun7i-a20-bananapro.dtb

sun7i-a20-bananapro.dts

Posted

Hello,

 

thank you for supplying these great instructions!

I confirm it is working, I got SPI running on Banana Pro with Kernel 4.9.32, following these steps on device tree blob and so on.

 

But: There is strange system behaviour when using SPI and usleep or msleep or QThread::msleep()... SPI stops working when thread is suspended with sleep after or before SPI command

Simplified example code:

for (Adresse=1; Adresse<8; Adresse++)
{
     SPI_RW(Adresse, 10);
     msleep(1);
}

This results in sometimes sending, sometimes not sending SPI-message, I checked that with an Oscilloscope.

 

My code worked perfectly on Kernel 3.4.10!

Could it be that SPI-Module and Thread-Timing access the same timer settings and overwrite them?

Thanks!

Posted

Just a quick note: It also works with kernel 4.12.0

One either has to redo the changes or copy the old dtb file over to the new dtb-4.12.0-sunxi folder, though (which on the other hand shouldn't be very surprising).

Guest
This topic is now closed to further replies.
×
×
  • Create New...

Important Information

Terms of Use - Privacy Policy - Guidelines