Basic SPI Overlay for a MikroBUS Cape

Howdy. After some years away I’ve come back to IoT and developing projects on my BeagleBone Black. And by some years, I mean the U-Boot method of loading overlays is completely new to me.

Here’s the .dts I’m writing:

/dts-v1/;
/plugin/;

/ {
  compatible = "ti,beaglebone", "ti,beaglebone-black";

  /* identification */
  part-number = "BB-MIKROCAPE-SPIHOST1";
  version = "00A0";

  /* state the resources this cape uses */
  exclusive-use =
    /* the pin header uses */
    "P9.28", /* spi1_cs0 */
    "P9.29", /* spi1_d0 */
    "P9.30", /* spi1_d1 */
    "P9.31", /* spi1_sclk */
    /* the hardware ip uses */
    "spi1";

  fragment@0 {
    target = <&am33xx_pinmux>;

    __overlay__ {

    spi1_pins_s0: spi1_pins_s0 {
    pinctrl-single,pins = <
      0x190 0x33    /* mcasp0_aclkx.spi1_sclk, INPUT_PULLUP | MODE3 */
      0x194 0x33    /* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
      0x198 0x13    /* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
      0x19c 0x13    /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
      0x164 0x12    /* eCAP0_in_PWM0_out.spi1_cs1 OUTPUT_PULLUP | MODE2 */
      >;
      };
    };
  };

  fragment@1 {

    target = <&spi1>;   /* spi1 is numbered correctly */

    __overlay__ {

      #address-cells = <1>;
      #size-cells = <0>;

      status = "okay";
      pinctrl-names = "default";
      pinctrl-0 = <&spi1_pins_s0>;

      /*cs-gpios = <0>;*/

      spidev@1 {
        compatible = "linux,spidev";
        reg = <0>;
        spi-max-frequency = <16000000>;
      };
    };
  };
 };

and I can compile it with dtc, copy the *.dtbo to /lib/firmware and then reference it in /boot/uEnv.txt:

debian@beaglebone:~/projects/mikro$ cat /boot/uEnv.txt
#Docs: http://elinux.org/Beagleboard:U-boot_partitioning_layout_2.0

uname_r=4.19.94-ti-r73
#uuid=
#dtb=

###U-Boot Overlays###
###Documentation: http://elinux.org/Beagleboard:BeagleBoneBlack_Debian#U-Boot_Overlays

###Master Enable
enable_uboot_overlays=1
###

###Overide capes with eeprom
#uboot_overlay_addr0=/lib/firmware/<file0>.dtbo
#uboot_overlay_addr1=/lib/firmware/<file1>.dtbo
#uboot_overlay_addr2=/lib/firmware/<file2>.dtbo
#uboot_overlay_addr3=/lib/firmware/<file3>.dtbo
###
###Additional custom capes
#uboot_overlay_addr4=/lib/firmware/<file4>.dtbo
#uboot_overlay_addr5=/lib/firmware/<file5>.dtbo
#uboot_overlay_addr6=/lib/firmware/<file6>.dtbo
#uboot_overlay_addr7=/lib/firmware/<file7>.dtbo
###
###Custom Cape
dtb_overlay=/lib/firmware/BB-MIKROCAPE-SPIHOST1.dtbo
###
###Disable auto loading of virtual capes (emmc/video/wireless/adc)
#disable_uboot_overlay_emmc=1
disable_uboot_overlay_video=1
disable_uboot_overlay_audio=1
#disable_uboot_overlay_wireless=1
#disable_uboot_overlay_adc=1

###
###PRUSS OPTIONS
###pru_rproc (4.14.x-ti kernel)
#uboot_overlay_pru=/lib/firmware/AM335X-PRU-RPROC-4-14-TI-00A0.dtbo
###pru_rproc (4.19.x-ti kernel)
uboot_overlay_pru=/lib/firmware/AM335X-PRU-RPROC-4-19-TI-00A0.dtbo
###pru_uio (4.14.x-ti, 4.19.x-ti & mainline/bone kernel)
#uboot_overlay_pru=/lib/firmware/AM335X-PRU-UIO-00A0.dtbo
###
###Cape Universal Enable
#enable_uboot_cape_universal=1
###
###Debug: disable uboot autoload of Cape
#disable_uboot_overlay_addr0=1
#disable_uboot_overlay_addr1=1
#disable_uboot_overlay_addr2=1
#disable_uboot_overlay_addr3=1
###
###U-Boot fdt tweaks... (60000 = 384KB)
#uboot_fdt_buffer=0x60000
###U-Boot Overlays###

cmdline=coherent_pool=1M net.ifnames=0 lpj=1990656 rng_core.default_quality=100 quiet

#In the event of edid real failures, uncomment this next line:
#cmdline=coherent_pool=1M net.ifnames=0 lpj=1990656 rng_core.default_quality=100 quiet video=HDMI-A-1:1024x768@60e

##enable Generic eMMC Flasher:
##make sure, these tools are installed: dosfstools rsync
#cmdline=init=/opt/scripts/tools/eMMC/init-eMMC-flasher-v3.sh

Yet the overlay isn’t loaded:

debian@beaglebone:/opt/scripts/tools$ sudo ./version.sh
git:/opt/scripts/:[931449639670238ab1c2085c1e4769a0638c1660]
eeprom:[A335BNLT000C2914BBBK1443]
model:[TI_AM335x_BeagleBone_Black]
dogtag:[BeagleBoard.org Debian Buster IoT Image 2020-04-06]
bootloader:[microSD-(push-button)]:[/dev/mmcblk0]:[U-Boot SPL 2019.04-00002-g07d5700e21 (Mar 06 2020 - 11:24:55 -0600)]:[location: dd MBR]
bootloader:[microSD-(push-button)]:[/dev/mmcblk0]:[U-Boot 2019.04-00002-g07d5700e21]:[location: dd MBR]
bootloader:[eMMC-(default)]:[/dev/mmcblk1]:[U-Boot SPL 2018.03-00002-gac9cce7c6a (Apr 05 2018 - 13:07:46 -0500)]:[location: dd MBR]
bootloader:[eMMC-(default)]:[/dev/mmcblk1]:[U-Boot 2018.03-00002-gac9cce7c6a]:[location: dd MBR]
UBOOT: Booted Device-Tree:[am335x-boneblack-uboot-univ.dts]
UBOOT: Loaded Overlay:[AM335X-PRU-RPROC-4-19-TI-00A0]
UBOOT: Loaded Overlay:[BB-ADC-00A0.bb.org-overlays]
UBOOT: Loaded Overlay:[BB-BONE-eMMC1-01-00A0.bb.org-overlays]
kernel:[4.19.94-ti-r73]
nodejs:[v10.24.0]
/boot/uEnv.txt Settings:
uboot_overlay_options:[enable_uboot_overlays=1]
uboot_overlay_options:[disable_uboot_overlay_video=1]
uboot_overlay_options:[disable_uboot_overlay_audio=1]
uboot_overlay_options:[uboot_overlay_pru=/lib/firmware/AM335X-PRU-RPROC-4-19-TI-00A0.dtbo]
uboot_overlay_options:[dtb_overlay=/lib/firmware/BB-MIKROCAPE-SPIHOST1.dtbo]
pkg check: to individually upgrade run: [sudo apt install --only-upgrade <pkg>]
pkg:[bb-cape-overlays]:[4.14.20210821.0-0~buster+20210821]
pkg:[bb-customizations]:[1.20221108.0-0~buster+20221108]
pkg:[bb-usb-gadgets]:[1.20220816.0-0~buster+20220816]
pkg:[bb-wl18xx-firmware]:[1.20211222.2-0~buster+20211222]
pkg:[kmod]:[26-1]
pkg:[librobotcontrol]:[1.0.5-git20200715.0-0~buster+20200716]
pkg:[firmware-ti-connectivity]:[20190717-2rcnee1~buster+20200305]
groups:[debian : debian adm kmem dialout cdrom floppy audio dip video plugdev users systemd-journal bluetooth netdev i2c gpio pwm eqep remoteproc admin spi iio docker tisdk weston-launch xenomai cloud9ide]
cmdline:[console=ttyO0,115200n8 bone_capemgr.uboot_capemgr_enabled=1 root=/dev/mmcblk0p1 ro rootfstype=ext4 rootwait coherent_pool=1M net.ifnames=0 lpj=1990656 rng_core.default_quality=100 quiet]
dmesg | grep remote
[   53.187523] remoteproc remoteproc0: wkup_m3 is available
[   53.267946] remoteproc remoteproc0: powering up wkup_m3
[   53.267980] remoteproc remoteproc0: Booting fw image am335x-pm-firmware.elf, size 217148
[   53.268276] remoteproc remoteproc0: remote processor wkup_m3 is now up
[   56.032002] remoteproc remoteproc1: 4a334000.pru is available
[   56.046477] remoteproc remoteproc2: 4a338000.pru is available
dmesg | grep pru
[   56.032002] remoteproc remoteproc1: 4a334000.pru is available
[   56.032158] pru-rproc 4a334000.pru: PRU rproc node pru@4a334000 probed successfully
[   56.046477] remoteproc remoteproc2: 4a338000.pru is available
[   56.046666] pru-rproc 4a338000.pru: PRU rproc node pru@4a338000 probed successfully
dmesg | grep pinctrl-single
[    0.955157] pinctrl-single 44e10800.pinmux: 142 pins, size 568
[    1.206027] pinctrl-single 44e10800.pinmux: pin PIN100 already requested by ocp:P9_31_pinmux; cannot claim for 481a0000.spi
[    1.217411] pinctrl-single 44e10800.pinmux: pin-100 (481a0000.spi) status -22
[    1.224624] pinctrl-single 44e10800.pinmux: could not request pin 100 (PIN100) from group pinmux_bbb_spi1_pins  on device pinctrl-single
dmesg | grep gpio-of-helper
[    0.969045] gpio-of-helper ocp:cape-universal: ready
lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
END

I’ve tried to follow along with all of the “new” overlay documentation but have been unsuccessful in loading my overlay. I’m guessing this:

[    0.955157] pinctrl-single 44e10800.pinmux: 142 pins, size 568
[    1.206027] pinctrl-single 44e10800.pinmux: pin PIN100 already requested by ocp:P9_31_pinmux; cannot claim for 481a0000.spi
[    1.217411] pinctrl-single 44e10800.pinmux: pin-100 (481a0000.spi) status -22
[    1.224624] pinctrl-single 44e10800.pinmux: could not request pin 100 (PIN100) from group pinmux_bbb_spi1_pins  on device pinctrl-single
dmesg | grep gpio-of-helper
[    0.969045] gpio-of-helper ocp:cape-universal: ready

is the root of the problem.

Remove this:

  exclusive-use =
    /* the pin header uses */
    "P9.28", /* spi1_cs0 */
    "P9.29", /* spi1_d0 */
    "P9.30", /* spi1_d1 */
    "P9.31", /* spi1_sclk */
    /* the hardware ip uses */
    "spi1";

and stick this:

/*
 * Free up the pins used by the cape from the pinmux helpers.
 */
&ocp {
	P9_28_pinmux { status = "disabled"; };
	P9_29_pinmux { status = "disabled"; };
	P9_30_pinmux { status = "disabled"; };
	P9_31_pinmux { status = "disabled"; };
};

before this block:

/ {
  compatible = "ti,beaglebone", "ti,beaglebone-black";

Regards,

Thanks as always @RobertCNelson , I’ll give that a shot and report back.

Thanks @RobertCNelson for putting me on the right track. /dev/spidev1.0 and /dev/spidev1.1 now enumerate with this .dts:

/dts-v1/;
/plugin/;


/ {

  compatible = "ti,beaglebone", "ti,beaglebone-black";

  /* identification */
  part-number = "BB-MIKROCAPE-SPIHOST1";
  version = "00A0";

  fragment@0 {
    target = <&ocp>;
    __overlay__ {
	P9_28_pinmux { status = "disabled"; };
	P9_29_pinmux { status = "disabled"; };
	P9_30_pinmux { status = "disabled"; };
	P9_31_pinmux { status = "disabled"; };
   };
  };

  fragment@1 {
    target = <&am33xx_pinmux>;

    __overlay__ {

    spi1_pins_s0: spi1_pins_s0 {
    pinctrl-single,pins = <
      0x190 0x33    /* mcasp0_aclkx.spi1_sclk, INPUT_PULLUP | MODE3 */
      0x194 0x33    /* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
      0x198 0x13    /* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
      0x19c 0x13    /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
      >;
      };

    };
  };

  fragment@2 {

    target = <&spi1>;   /* spi1 is numbered correctly */

    __overlay__ {

      #address-cells = <1>;
      #size-cells = <0>;

      status = "okay";
      pinctrl-names = "default";
      pinctrl-0 = <&spi1_pins_s0>;

      spidev@1 {
        compatible = "linux,spidev";
        reg = <0>;
        spi-max-frequency = <16000000>;
      };
    };
  };
 };

The show-pins script output:

P9.31 / hdmi audio clk           100 fast rx  up  3 spi 1 clk        spi@481a0000 (spi1_pins_s0)
P9.29 / hdmi audio fs            101 fast rx  up  3 spi 1 d0 miso    spi@481a0000 (spi1_pins_s0)
P9.30                            102 fast     up  3 spi 1 d1 mosi    spi@481a0000 (spi1_pins_s0)
P9.28 / hdmi audio data          103 fast     up  3 spi 1 cs 0       spi@481a0000 (spi1_pins_s0)

One quick question: version.sh doesn’t show the overlay loaded:

UBOOT: Booted Device-Tree:[am335x-boneblack-uboot-univ.dts]
UBOOT: Loaded Overlay:[AM335X-PRU-RPROC-4-19-TI-00A0]
UBOOT: Loaded Overlay:[BB-ADC-00A0.bb.org-overlays]
UBOOT: Loaded Overlay:[BB-BONE-eMMC1-01-00A0.bb.org-overlays]
kernel:[4.19.94-ti-r73]
nodejs:[v10.24.0]
/boot/uEnv.txt Settings:
uboot_overlay_options:[enable_uboot_overlays=1]
uboot_overlay_options:[disable_uboot_overlay_video=1]
uboot_overlay_options:[disable_uboot_overlay_audio=1]
uboot_overlay_options:[uboot_overlay_pru=/lib/firmware/AM335X-PRU-RPROC-4-19-TI-00A0.dtbo]
uboot_overlay_options:[dtb_overlay=/lib/firmware/BB-MIKROCAPE-SPIHOST1.dtbo]

but there are no errors in the rest of the output. Should I expect to see “Loaded Overlay” and need to continue investigating?

Update: I looped back MOSI and MISO in slot 1 of the MikroBUS cape, compiled the kernel spidev_test and things looked promising:

debian@beaglebone:~$ ./spidev_test  -D /dev/spidev1.0 -v
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 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  |......@.........................|
debian@beaglebone:~$ ./spidev_test  -D /dev/spidev1.0 -v -p "12345678"
spi mode: 0x0
bits per word: 8
max speed: 500000 Hz (500 kHz)
TX | 31 32 33 34 35 36 37 38 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  |12345678|
RX | 31 32 33 34 35 36 37 38 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __  |12345678|

Hopefully that’s a good sign things are working.

It’s just a hint that we add in the overlay to help version.sh detect it…

/*
 * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
 */
&{/chosen} {
	overlays {
		BB-MIKROCAPE-SPIHOST1 = __TIMESTAMP__;
	};
};

It doesn’t change the functionally of the overlay in anyway, just a hint to userspace.

Regards,

1 Like

Thanks @RobertCNelson . It’s clear to me that I’m using an “older” version of the .dts format, one with a lot of fragment@ statements. Let me clean that up and post it for posterity.

@RobertCNelson , a quick question here - I cannot seem to get dtc to compile the &{/chosen} syntax you provided above. I’m using DCT 1.4.7.

debian@beaglebone:~/projects/mikro$ make
dtc -O dtb -o BB-MIKROCAPE-SPIHOST1.dtbo -b 0 -@ BB-MIKROCAPE-SPIHOST1.dts
Error: BB-MIKROCAPE-SPIHOST1.dts:6.27-28 syntax error
FATAL ERROR: Unable to parse input tree

where the file looks like:

/dts-v1/;
/plugin/;

&{/chosen} {
	overlays {
		BB-MIKROCAPE-SPIHOST1 = __TIMESTAMP__;
	};
};

&ocp {
	P9_28_pinmux { status = "disabled"; };
	P9_29_pinmux { status = "disabled"; };
	P9_30_pinmux { status = "disabled"; };
	P9_31_pinmux { status = "disabled"; };
   };

&am33xx_pinmux {
    spi1_pins_s0: spi1_pins_s0 {
    pinctrl-single,pins = <
      0x190 0x33    /* mcasp0_aclkx.spi1_sclk, INPUT_PULLUP | MODE3 */
      0x194 0x33    /* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
      0x198 0x13    /* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
      0x19c 0x13    /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
      >;
      };
};

&spi1 {

      #address-cells = <1>;
      #size-cells = <0>;

      status = "okay";
      pinctrl-names = "default";
      pinctrl-0 = <&spi1_pins_s0>;

      spidev@1 {
        compatible = "linux,spidev";
        reg = <0>;
        spi-max-frequency = <16000000>;
      };
    };

dtc 1.4.7 should build it fine…

Edit, ah… i bet your makefile is not calling the gcc-preprocessors…

&{/chosen} {
	overlays {
		BB-MIKROCAPE-SPIHOST1 = "somerandomtext";
	};
};

Regards,

Thanks again @RobertCNelson .

While I did figure out the precompiler to get __TIMESTAMP__ converted I went with just using a handwritten timestamp in quotes. After that, success!

bootloader:[eMMC-(default)]:[/dev/mmcblk1]:[U-Boot 2018.03-00002-gac9cce7c6a]:[location: dd MBR]
UBOOT: Booted Device-Tree:[am335x-boneblack-uboot-univ.dts]
UBOOT: Loaded Overlay:[AM335X-PRU-RPROC-4-19-TI-00A0]
UBOOT: Loaded Overlay:[BB-ADC-00A0.bb.org-overlays]
UBOOT: Loaded Overlay:[BB-BONE-eMMC1-01-00A0.bb.org-overlays]
UBOOT: Loaded Overlay:[BB-MIKROCAPE-SPIHOST1]

The final .dts to support a SPI device in slot 1 of the MikroBUS cape:

/dts-v1/;
/plugin/;

&{/chosen} {
  overlays {
    BB-MIKROCAPE-SPIHOST1 = "2022-11-30";
  };
};

&ocp {
	P9_28_pinmux { status = "disabled"; };
	P9_29_pinmux { status = "disabled"; };
	P9_30_pinmux { status = "disabled"; };
	P9_31_pinmux { status = "disabled"; };
};

&am33xx_pinmux {
    spi1_pins_s0: spi1_pins_s0 {
    pinctrl-single,pins = <
      0x190 0x33    /* mcasp0_aclkx.spi1_sclk, INPUT_PULLUP | MODE3 */
      0x194 0x33    /* mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
      0x198 0x13    /* mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
      0x19c 0x13    /* mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
      >;
      };
};

&spi1 {
  #address-cells = <1>;
  #size-cells = <0>;

  status = "okay";
  pinctrl-names = "default";
  pinctrl-0 = <&spi1_pins_s0>;

  spidev@1 {
    compatible = "linux,spidev";
    reg = <0>;
    spi-max-frequency = <16000000>;
  };
};

I truly appreciate your help.