As opposed to I2C, SPI on Fedora ARM doesn’t work out of the box. In this post I will describe what I did in order to use a Nokia 5110 LCD display on a Raspberry Pi 3 running Fedora 28 (Fedora-Minimal-armhfp-28).

This is due to the fact that the device tree definition file shipped with the upstream kernel doesn’t include all the necessary bits. And some other thing.

Fedora LCD display

Disclaimer: I’m not an engineer nor a kernel developer. This post comes from try and fail tasks, googling for info, observations, etc. Pay attention when working with the GPIO pins and the electricity. I’m still alive and my RPi still works pretty well, but damages to your RPi coming from tasks here described cannot be attributed to me :-) As usual, forgive my English. The purpose of this post is for test and tinkering.

How to add the required bits

Look into a DTB file

Fedora on the Raspberry Pi 3 load the bcm2837-rpi-3-b dtb located in /boot/dtb/bcm2837-rpi-3-b.dtb. Since this file is compiled you have to use some command line tool to read the content. The human readable format is DTS (Device Tree Source Format), more info here. You can compile and decompile them using the dtc command.

sudo fdtdump /boot/dtb/bcm2837-rpi-3-b.dtb

To get a specific value:

sudo fdtget /boot/dtb/bcm2837-rpi-3-b.dtb /soc/spi@7e204000 status

You will see that the spi status is disabled. You could use fdtput to enable it, but it is not sufficient.

Install some RPM packages

Let’s install some packages. Maybe there are other ways to put the necessary bits in place. But I was unable to do it better.

sudo dnf update
sudo systemcl reboot  # if there are kernel updates

sudo dnf install -y rpmdevtools
sudo dnf builddep -y kernel

Messing with the kernel sources

Let’s install the kernel source.

sudo dnf install -y rpmdevtools
sudo dnf builddep -y kernel

dnf download --source kernel
rpm -i kernel-*.src.rpm
cd rpmbuild

Run “rpmbuild -bp” for extracting source tree.

rpmbuild -bp SPECS/kernel.spec

Now go to the arm dts directory

cd ~/rpmbuild/BUILD/kernel-4.17.fc28/linux-4.17.14-202.fc28.armv7hl/arch/arm/boot/dts

Download and apply these patches. The involved files are: bcm2837-rpi-3-b.dts, bcm283x.dtsi and bcm2835-rpi.dtsi.

bcm2837-rpi-3-b.dts.patch
bcm283x.dtsi.patch
bcm2835-rpi.dtsi.patch

The last one contains the gpiomem descriptor, that as far as I can understand, it is needed by various python libraries.

Now compile the final dtb file

cpp -I../../../../include -E -P -x assembler-with-cpp bcm2837-rpi-3-b.dts | dtc -I dts -O dtb -o bcm2837-rpi-3-b.dtb -

In the previous step we didn’t enable the spi device, we can do that using th fdtput command

fdtput --type s bcm2837-rpi-3-b.dtb /soc/spi@7e204000 status okay

At this point we can copy the file to the final destination and reboot the Raspberry.

sudo cp /boot/dtb/bcm2837-rpi-3-b.dtb /boot/dtb/bcm2837-rpi-3-b.dtb.ORIG
sudo cp ./bcm2837-rpi-3-b.dtb /boot/dtb/bcm2837-rpi-3-b.dtb

sudo systemctl reboot

If everything seems to be all right, you should see the devices under /dev

ls -la /dev/spidev*
crw-------. 1 root root 153, 0 May 11 12:26 /dev/spidev0.0
crw-------. 1 root root 153, 1 May 11 12:26 /dev/spidev0.1

Test the SPI interface

Let’s use a tool included in the kernel sources.

cd ~/rpmbuild/BUILD/kernel-4.17.fc28/linux-4.17.14-202.fc28.armv7hl/tools/spi/
make

Running this program

sudo ./spidev_fdx /dev/spidev0.0

You should see

/dev/spidev0.0: spi mode 0x0, 8 bits per word, 125000000 Hz max

Running this other program

sudo ./spidev_test -D /dev/spidev0.0

This should be the result:

spi mode: 0x0
bits per word: 8
max speed: 500000 Hz (500 KHz)

gpiomem

Stuff like Adafruit_Nokia_LCD, and many drivers and libraries require the existence of /dev/gpiomem, as far as I can understand. But the bcm2835-gpiomem kernel module is not upstream, so you need to download and compile it.

Again: maybe there are better ways to achieve this task.

sudo dnf install kernel-devel
mkdir /var/tmp/bcm2835-gpiomem
cd /var/tmp/bcm2835-gpiomem
curl -O https://raw.githubusercontent.com/raspberrypi/linux/rpi-4.17.y/drivers/char/broadcom/bcm2835-gpiomem.c
vi Makefile

In the Makefile put these lines:

obj-m := bcm2835-gpiomem.o
KDIR  := /lib/modules/$(shell uname -r)/build
PWD   := $(shell pwd)
default:
  $(MAKE) -C $(KDIR) M=$(PWD) modules

Note: before $(MAKE) there is a TAB.

Now let’s compile the module.

make -C /lib/modules/`uname -r`/build M=`pwd` modules
sudo make -C /lib/modules/`uname -r`/build M=`pwd` modules_install

And let’s try to load it:

sudo modprobe bcm2835-gpiomem

Verify that /dev/gpiomem is in place.

Let’s try the LCD DISPLAY

Wiring

Follow some better guide related to how to wire the Nokia 5110 LDC display to the RPi.

RPi Physical pin RPi pin LCD pin
18 GPIO 24 RST
24 CE0 CE
16 GPIO 23 DC
19 MOSI DIN
23 SCLK CLK
1 3.3V VCC
11 GPIO 17 BL
6 GND GND

Using the Adafruit Nokia LCD Python library

sudo dnf install python3-devel python3-pillow python3-RPi.GPIO

git clone https://github.com/adafruit/Adafruit_Nokia_LCD.git
cd Adafruit_Nokia_LCD
sudo python3 setup.py install
cd examples

Run some example code.

kernel updates

Remember that the /boot/dtb is a link to a directory related to the current kernel and it will be changed at every kernel update, so the bcm2837-rpi-3-b.dtb loaded at boot will be replaced.