Reputation: 73
I have a DE1-SoC FPGA running Ubuntu 16.04 via the microSD card. I'm somewhat new to the device-tree, but have managed to figure out somewhat how to enable the various peripherals on the board by decompiling the .dtb file into a .dts file using dtc. I did that and edited the .dts file in nano to change the SPI ports from "disabled" to "okay". I then recompiled the .dtb file from the modified .dts file (I also erased the .dts file and re-decompiled a second .dts file to see if the changed took affect, and they did).
At this point, I reboot the system, and go to cd/dev/ but there is not spidev or spi* or spidev* listed. When I go to cd/proc/device-tree, I have the following listed:
ubuntu@DE1_SoC:/proc/device-tree$ dir
3-3-v-regulator chosen leds name
#address-cells compatible __local_fixups__ #size-cells
aliases cpus memory soc
bridge@0xff200000 intc@fffed000 model __symbols__
And when I navigate to the /soc/ folder, I have the following, which is consistent with the .dts file I have:
ubuntu@DE1_SoC:/proc/device-tree/soc$ dir
#address-cells gpio@ff70a000 #size-cells
amba i2c@ffc04000 snoop-control-unit@fffec000
base-fpga-region i2c@ffc05000 spi@ff705000
can@ffc00000 i2c@ffc06000 spi@fff00000
can@ffc01000 i2c@ffc07000 spi@fff01000
clkmgr@ffd04000 interrupt-parent sram@ffff0000
compatible l2-cache@fffef000 sysmgr@ffd08000
device_type l2edac@xffd08140 timer0@ffc08000
dwmmc0@ff704000 l3regs@0xff800000 timer1@ffc09000
ethernet@ff700000 name timer2@ffd00000
ethernet@ff702000 nand@ff900000 timer3@ffd01000
fpga2sdram-bridge ocramedac@ffd08144 timer@fffec600
fpga-bridge@ff400000 ranges usb@ffb00000
fpga-bridge@ff500000 rstmgr@ffd05000 usb@ffb40000
fpga-bridge@ff600000 sdramedac usbphy@0
fpga-mgr@ff706000 sdr@ffc25000 watchdog@ffd02000
gpio@ff708000 serial0@ffc02000 watchdog@ffd03000
gpio@ff709000 serial1@ffc03000
So, I'm not sure what I'm doing wrong that my serial peripheral interfaces are not working. The end goal: the SPI on the FPGA connects to an onboard ADC (AD7928), which I would like to access via Linux using a program written in C. The i2C work fine, but for some reason the SPI is not responding.
I think I might be missing a step, but at this point I am kinda lost so any help would be great.
EDIT: Forgot to add the .dts entry for the SPI:
spi@fff00000 {
compatible = "snps,dw-apb-ssi";
#address-cells = <0x1>;
#size-cells = <0x0>;
reg = <0xfff00000 0x1000>;
interrupts = <0x0 0x9a 0x4>;
num-cs = <0x4>;
tx-dma-channel = <0x2c 0x10>;
rx-dma-channel = <0x2c 0x11>;
clocks = <0x11>;
status = "okay";
linux,phandle = <0x59>;
phandle = <0x59>;
};
spi@fff01000 {
compatible = "snps,dw-apb-ssi";
#address-cells = <0x1>;
#size-cells = <0x0>;
reg = <0xfff01000 0x1000>;
interrupts = <0x0 0x9b 0x4>;
num-cs = <0x4>;
tx-dma-channel = <0x2c 0x14>;
rx-dma-channel = <0x2c 0x15>;
clocks = <0x11>;
status = "okay";
linux,phandle = <0x5a>;
phandle = <0x5a>;
};
And the addresses are consistent with the board's datasheet for the SPIM.
Made a little leeway by adding editing the .dts some more:
spi@fff00000 {
compatible = "snps,dw-apb-ssi";
#address-cells = <0x1>;
#size-cells = <0x0>;
reg = <0xfff00000 0x1000>;
interrupts = <0x0 0x9a 0x4>;
num-cs = <0x4>;
tx-dma-channel = <0x2c 0x10>;
rx-dma-channel = <0x2c 0x11>;
clocks = <0x11>;
status = "okay";
linux,phandle = <0x59>;
phandle = <0x59>;
spidev@0 {
compatible = "spidev";
reg = <0x0>;
spi-max-frequency = <0xb71b00>;
enable-dma = <0x0>;
}
Now spidev32766.0 is showing up in my /dev/ folder.
Upvotes: 0
Views: 1717
Reputation: 802
spidev32766.0 is device node you got after you added device tree nodespidev@0
for SPI device on first SPI bus (controller) spi@fff00000
with chip select 0.
Frequency property spi-max-frequency = <0xb71b00>
by convention should be put in decimal format 12000000, instead of hex, and in new versions of spidev.c, driver will complain about compatible = "spidev"
property, as this property should describe real HW not some SW abstraction.
This 32766 bus(controller) number is dynamically allocated by the Kernel and is completely legal.
In older Kernels, before device tree files, bus number had to be defined in board file platform data e.g.: .bus_num = 0,
As previously said there are no SPI bus(controller) device nodes spiX
under/dev
filesystem, only clients(chip) device nodes spidevX.Y
.
spidev.c
is a special kind of driver which is registered for generic SPI client(chip) devices, and it's main goal is to export Kernel low level SPI API to userspace, by creating character device nodes under /dev
interface.
But if your goal is SPI driver for ADC, maybe it is better to use a existing Linux SPI driver for that chip, like e.g. for AD7791, or to write your own. Linux provides support for Industrial I/O Subsystem (iio) devices like analog to digital converters.
Linux Kernel Configuration
Device Drivers --->
...
<*> Industrial I/O support --->
--- Industrial I/O support
...
Analog to digital converters --->
...
<*> Analog Devices ADXYZ* ADC driver
In that case Linux will export your ADC device functionality to userspace in /sys
filesystem:
/sys/bus/iio/devices/iio:deviceX
with device attributes accessible as files:
-r--r--r-- 1 root root 4096 Jan 1 04:18 name
drwxr-xr-x 2 root root 0 Jan 1 04:18 power
-rw-r--r-- 1 root root 4096 Jan 1 04:18 sampling_frequency
-r--r--r-- 1 root root 4096 Jan 1 04:18 sampling_frequency_available
Upvotes: 1