A couple of weeks ago I finally moved my Arch Linux Arm based Raspberries to the mainline Linux kernel (linux-aarch64
) and u-boot
. The transition was pretty smooth with one exception: the spidev
driver, which is needed to show rainbows (and other information) on the attached Pimoroni Display-O-HAT. Most probably, the reason of this absence is because the spidev
driver should not be declared in the Device Tree according to the kernel developers.
It is not rocket science, however I couldn’t find a quick explanation about how to add a Device Tree overlay to restore the functionality. So, here we are!
The first step is to create the Device Tree Overlay, check the source below, which can be put in a file spidev.dts
. Note we are faking a particular device driven via spidev
. Using spidev
directly will trigger a loudly kernel WARNING. You can compile the overlay with:
dtc -@ -Hepapr -I dts -O dtb -o spidev.dto spidev.dts
The content of spidev.dts
is:
/dts-v1/;
/plugin/;
/{
compatible = "brcm,bcm2835";
fragment@0 {
target-path = "/soc/gpio@7e200000";
__overlay__ {
spi0_pins: spi0_pins {
brcm,pins = <0x09 0x0a 0x0b>;
brcm,function = <0x04>;
phandle = <0x0d>;
};
spi0_cs_pins: spi0_cs_pins {
brcm,pins = <0x08 0x07>;
brcm,function = <0x01>;
phandle = <0x0e>;
};
};
};
fragment@1 {
target-path = "/soc/spi@7e204000";
__overlay__ {
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
cs-gpios = <&gpio 8 1>, <&gpio 7 1>;
status = "okay";
spidev0: spidev@0{
compatible = "lwn,bk4";
reg = <0>; /* CE0 */
#address-cells = <1>;
#size-cells = <0>;
spi-max-frequency = <125000000>;
};
spidev1: spidev@1{
compatible = "lwn,bk4";
reg = <1>; /* CE1 */
#address-cells = <1>;
#size-cells = <0>;
spi-max-frequency = <125000000>;
};
};
};
};
The next step is to change the u-boot boot script to load the overlay. This is distribution dependent, for Arch Liunx Arm it is /boot/boot.txt
. The added lines are marked by a comment. Don’t forget to copy spidev.dto
to /boot/dtbs/ and to run ./mkscr
.
# After modifying, run ./mkscr
# Set root partition to the second partition of boot device
part uuid ${devtype} ${devnum}:2 uuid
setenv bootargs console=ttyS1,115200 console=tty0 root=PARTUUID=${uuid} rw rootwait smsc95xx.macaddr="${usbethaddr}"
if load ${devtype} ${devnum}:${bootpart} ${kernel_addr_r} /Image; then
if load ${devtype} ${devnum}:${bootpart} ${fdt_addr_r} /dtbs/${fdtfile}; then
# Needed for DT Overlay
fdt addr ${fdt_addr_r}
fdt resize
setexpr fdtovaddr ${fdt_addr_r} + F000
load ${devtype} ${devnum}:${bootpart} ${fdtovaddr} /dtbs/spidev.dto && fdt apply ${fdtovaddr}
# End of DT Overlay
if load ${devtype} ${devnum}:${bootpart} ${ramdisk_addr_r} /initramfs-linux.img; then
booti ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} ${fdt_addr_r};
else
booti ${kernel_addr_r} - ${fdt_addr_r};
fi;
fi;
fi
Last step, force load spidev.ko
by creating /etc/modules-load.d/spidev.conf
:
# For the PI hats
spidev
And you should be all set!