Can't seem to enable SPI0 on Beaglebone Black on Debian Jessie with 4.1.6 kernel

I followed the directions here (as best I could given that device tree filenames have changed position again … sigh): http://elinux.org/BeagleBone_Black_Enable_SPIDEV

Something seems wrong as I’m picking up /dev/spidev1.0 instead of /dev/spidev0.0

And when I try to mmap the SPI region and read it, I get a bus error.

Any suggestions?

Thanks.

`

root@arm:~# uname -a
Linux arm 4.1.6-ti-r11 #1 SMP PREEMPT Tue Aug 18 21:36:11 UTC 2015 armv7l GNU/Linux

`

I used this file for the overlay:

`

root@arm:~# cat BB-SPI0-01-00A0.dts
/dts-v1/;
/plugin/;

/ {
compatible = “ti,beaglebone”, “ti,beaglebone-black”;

/* identification */
part-number = “spi0pinmux”;

fragment@0 {
target = <&am33xx_pinmux>;
overlay {
spi0_pins_s0: spi0_pins_s0 {
pinctrl-single,pins = <
0x150 0x30 /* spi0_sclk, INPUT_PULLUP | MODE0 /
0x154 0x30 /
spi0_d0, INPUT_PULLUP | MODE0 /
0x158 0x10 /
spi0_d1, OUTPUT_PULLUP | MODE0 /
0x15c 0x10 /
spi0_cs0, OUTPUT_PULLUP | MODE0 */

;
};
};
};

fragment@1 {
target = <&spi0>;
overlay {
#address-cells = <1>;
#size-cells = <0>;

status = “okay”;
pinctrl-names = “default”;
pinctrl-0 = <&spi0_pins_s0>;

spidev@0 {
spi-max-frequency = <24000000>;
reg = <0>;
compatible = “linux,spidev”;
};
};
};
};

`

But when I enable it I seem to be picking up then wrong SPI interface?

`

root@arm:~# echo BB-SPI0-01 > /sys/devices/platform/bone_capemgr/slots
root@arm:~# ls -al /dev/spidev*
crw-rw---- 1 root spi 153, 0 Aug 25 10:02 /dev/spidev1.0

`

I can see it in the pin groups:

`

root@arm:~# cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pingroups
registered pin groups:
group: pinmux_clkout2_pin
pin 109 (44e109b4.0)

group: pinmux_uart0_pins
pin 92 (44e10970.0)
pin 93 (44e10974.0)

group: pinmux_mmc1_pins
pin 60 (44e108f0.0)
pin 61 (44e108f4.0)
pin 62 (44e108f8.0)
pin 63 (44e108fc.0)
pin 64 (44e10900.0)
pin 65 (44e10904.0)
pin 104 (44e109a0.0)
pin 88 (44e10960.0)

group: pinmux_mmc1_pins_sleep
pin 60 (44e108f0.0)
pin 61 (44e108f4.0)
pin 62 (44e108f8.0)
pin 63 (44e108fc.0)
pin 64 (44e10900.0)
pin 65 (44e10904.0)
pin 104 (44e109a0.0)
pin 88 (44e10960.0)

group: user_leds_s0
pin 21 (44e10854.0)
pin 22 (44e10858.0)
pin 23 (44e1085c.0)
pin 24 (44e10860.0)

group: pinmux_i2c0_pins
pin 98 (44e10988.0)
pin 99 (44e1098c.0)

group: pinmux_i2c2_pins
pin 94 (44e10978.0)
pin 95 (44e1097c.0)

group: cpsw_default
pin 66 (44e10908.0)
pin 67 (44e1090c.0)
pin 68 (44e10910.0)
pin 69 (44e10914.0)
pin 70 (44e10918.0)
pin 71 (44e1091c.0)
pin 72 (44e10920.0)
pin 73 (44e10924.0)
pin 74 (44e10928.0)
pin 75 (44e1092c.0)
pin 76 (44e10930.0)
pin 77 (44e10934.0)
pin 78 (44e10938.0)
pin 79 (44e1093c.0)
pin 80 (44e10940.0)

group: cpsw_sleep
pin 66 (44e10908.0)
pin 67 (44e1090c.0)
pin 68 (44e10910.0)
pin 69 (44e10914.0)
pin 70 (44e10918.0)
pin 71 (44e1091c.0)
pin 72 (44e10920.0)
pin 73 (44e10924.0)
pin 74 (44e10928.0)
pin 75 (44e1092c.0)
pin 76 (44e10930.0)
pin 77 (44e10934.0)
pin 78 (44e10938.0)
pin 79 (44e1093c.0)
pin 80 (44e10940.0)

group: davinci_mdio_default
pin 82 (44e10948.0)
pin 83 (44e1094c.0)

group: davinci_mdio_sleep
pin 82 (44e10948.0)
pin 83 (44e1094c.0)

group: spi0_pins_s0
pin 84 (44e10950.0)
pin 85 (44e10954.0)
pin 86 (44e10958.0)
pin 87 (44e1095c.0)

`

Program which returns a Bus Error:

`

root@arm:~/gpio# clang -Wall -g -o spi_test spi.c
root@arm:~/gpio# ./spi_test
Bus error
root@arm:~/gpio# cat spi.c

#include <stdint.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/mman.h>

#include <assert.h>

// Hunt these addresses down from ls -al /sys/devices/platform/ocp | grep gpio
// You can also pull them from the TI manual (spruh73l.pdf)

#define MCSPI0_BASE 0x48030000
#define MCSPI0_SIZE 0x00001000

#define MCSPI_REVISION (0x000)
#define MCSPI_SYSCONFIG (0x110)
#define MCSPI_SYSSTATUS (0x114)

#define MCSPI_SYST (0x124)
#define MCSPI_MODULCTRL (0x128)

#define MCSPI_CH0CONF (0x12C)
#define MCSPI_CH0STAT (0x130)
#define MCSPI_CH0CTRL (0x134)

int main(int argc, char *argv[])
{
uint8_t volatile * bbMCSPI0Map = NULL;
uint32_t ui32tmp = 0;

int fd = open("/dev/mem", O_RDWR);

bbMCSPI0Map = mmap(0, MCSPI0_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, MCSPI0_BASE);
assert(bbMCSPI0Map != MAP_FAILED);

ui32tmp = *(uint32_t volatile *)(bbMCSPI0Map + MCSPI_SYSSTATUS);
assert((ui32tmp & 0x00000001) != 0);

// while(1) {
// }

close(fd);

return 0;
}

`

Well, I still don’t know why the overlays aren’t working, but I seem to have gotten the clocks toggled correctly to avoid a SIGBUS Bus Error.

This code turns on the clocks and waits for them to become stable. Then it reads the SPI0 version register for confirmation.

`

#include <stdint.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/mman.h>

#include <stdio.h>
#include <assert.h>

// Hunt these addresses down from ls -al /sys/devices/platform/ocp | grep gpio
// You can also pull them from the TI manual (spruh73l.pdf)

#define CM_PER_BASE 0x44E00000
#define CM_PER_SIZE 0x4000

#define CM_PER_SPI0_CLKCTRL 0x4C
#define CM_PER_L4LS_CLKCTRL 0x60

#define MCSPI0_BASE 0x48030000
#define MCSPI0_SIZE 0x00001000

#define MCSPI_REVISION (0x000)
#define MCSPI_SYSCONFIG (0x110)
#define MCSPI_SYSSTATUS (0x114)

#define MCSPI_SYST (0x124)
#define MCSPI_MODULCTRL (0x128)

#define MCSPI_CH0CONF (0x12C)
#define MCSPI_CH0STAT (0x130)
#define MCSPI_CH0CTRL (0x134)

int main(int argc, char *argv[])
{

uint8_t volatile * bbCM_PERMap = NULL;
uint8_t volatile * bbMCSPI0Map = NULL;
uint32_t ui32tmp = 0;
uint32_t volatile * ppui32tmp = NULL;

int fd = open("/dev/mem", O_RDWR);

bbCM_PERMap = mmap(0, CM_PER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, CM_PER_BASE);
assert(bbCM_PERMap != MAP_FAILED);

*(uint32_t volatile *)(bbCM_PERMap+CM_PER_L4LS_CLKCTRL) = 0x00000002; // Enable L4LS_CLK
do {
ui32tmp = *(uint32_t volatile *)(bbCM_PERMap+CM_PER_SPI0_CLKCTRL);
sleep(1);
} while (((ui32tmp >> 16) & 0x00000003) != 0); // Wait for L4LS_CLK to come up

*(uint32_t volatile *)(bbCM_PERMap+CM_PER_SPI0_CLKCTRL) = 0x00000002; // Enable SPI0 CLK
do {
ui32tmp = *(uint32_t volatile *)(bbCM_PERMap+CM_PER_SPI0_CLKCTRL);
sleep(1);
} while (((ui32tmp >> 16) & 0x00000003) != 0); // Wait for module to come up

bbMCSPI0Map = mmap(0, MCSPI0_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, MCSPI0_BASE);
assert(bbMCSPI0Map != MAP_FAILED);

ppui32tmp = (uint32_t volatile *)bbMCSPI0Map;
assert(bbMCSPI0Map == ppui32tmp);
ui32tmp = *ppui32tmp; // Read the revision register
printf(“SPI0 Revision: 0x%08x\n”, ui32tmp);

close(fd);

return 0;
}

`