UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

Reply

How to use XPS SPI core driver in linux?

Accepted Solution Solved
Contributor
Posts: 48
Registered: ‎07-08-2008
Accepted Solution

How to use XPS SPI core driver in linux?

[ Edited ]

Hello all,

 

we have a custom board based on the ML507 (Virtex5 FX70T). We have created a XPS Project wich has 4 SPI Cores, each of them with different slave number and different bit width. Each of the SPI cores is used to communicate with ADC devices and DAC devices. We have connected the 4 interrupt signals of the SPI Cores to the interrupt controller. In the Linux configuration Menu we have selected the Xilinx SPI Driver, SPI driver, SPI Bitbang driver, etc.

 

We have successfully generated an Embedded Linux for this board and it starts correctly. In the start up sequence, Linux detects correctly four SPI cores as it is shown below:

 

xilinx-xps-spi f3000080.xps-spi: at 0xF3000080 mapped to 0xe1074080, irq=16
xilinx-xps-spi f1000000.xps-spi: at 0xF1000000 mapped to 0xe1078000, irq=17
xilinx-xps-spi f6000080.xps-spi: at 0xF6000080 mapped to 0xe107c080, irq=18
xilinx-xps-spi f2000000.xps-spi: at 0xF2000000 mapped to 0xe9082000, irq=19

 

 

After linux has started up, we are not sure how to access those SPI devices. We have done research about SPI linux drivers, and we think there are two drivers that can be used:

 

- Linux SPI driver (spidev.c, spi.c, spi.h, ...): this driver communicates with an SPI device. In spidev.c

- Linux Xilinx SPI Driver (xilinx_spi.c, xilinx_spi_of.c, etc): uses SPI driver functions above it to communicate with the XPS SPI core.

 

However, we still don't know how we can communicate with the SPI cores from linux user code. We are not sure if we have to create a device under /dev directory or use other driver functions to initialize the driver. We have seen that the lines shown at the beggining of this post:

 

xilinx-xps-spi f3000080.xps-spi: at 0xF3000080 mapped to 0xe1074080, irq=16
xilinx-xps-spi f1000000.xps-spi: at 0xF1000000 mapped to 0xe1078000, irq=17
xilinx-xps-spi f6000080.xps-spi: at 0xF6000080 mapped to 0xe107c080, irq=18
xilinx-xps-spi f2000000.xps-spi: at 0xF2000000 mapped to 0xe9082000, irq=19

 

are created by xilinx_spi.c linux driver, which means that this driver makes the ioremap of the SPI core registers to access them from the virtual memory space.

 

Still, we are not sure if we have to use mknod to create a device under /dev directory, (we don't know what minor number we have to assign to them, the major number must be the number that appears for SPI in /proc/devices, that is, 153), because we have read in the linux spi driver that if the SPI core has 6 spi select lines, then we have to create 6 devices using the sintax:

 

/dev/spidevB.C

 

where B is the SPI device identifier and C is the chipselect number.

 

We have seen in another part of the driver that this nodes under /dev should be created using mdev, but we have tried to do what is explained in the link below:

 

http://wildanm.wordpress.com/2007/08/21/mdev-mini-udev-in-busybox/

 

with no results.

 

We are a bit confused because if there is a Xilinx SPI Driver under Linux embedded it musn't be too hard to communicate with the XPS SPI Core, but we still don't know how to achieve that. Any suggestions?

 

 

Regards,

 

Borja


Accepted Solutions
Contributor
Posts: 48
Registered: ‎07-08-2008

Re: How to use XPS SPI core driver in linux?

[ Edited ]

Hello John,

 

here is the explanation post:

 

 

How to configure and use XPS SPI core in Linux (EDK 10.1 and Linux git 2.6.33)

 

1.- First, we need to include the SPI IP core in our XPS project. It is very important to connect he interrupt of the core to the Interrupt controller and include it in the Connected Interrupts, like it is shown below. In our example project we have 4 spi cores: Generic_SPI, xps_spi_0, xps_spi_1 and xps_spi_2, each of them with different slave number, bit width, ... configuration:

 

 

 

2.- After that, we need to include some lines in the dts, where the SPI cores are defined. We need to add the lines marked in red below. We need to include the address and size of the cells for each device (you can use the ones listed here for any SPI core) and for each slave, we need to include the definition of a device. In this case, we have 2 slaves, so we need to define two devices (device@0 and device@1) and we need to add the lines compatible = "spidev", reg = <slave number>, and the spi-max-frequency = <frequency defined in the SPI core in XPS> (in our case, the frequency is 100 MHz / 32 = 3.125.000 MHz):

 

 

xps_spi_1: xps-spi@f6000080 {
            compatible = "xlnx,xps-spi-2.00.b", "xlnx,xps-spi-2.00.a";
            #address-cells=<1>;
            #size-cells=<0>;

            interrupt-parent = <&xps_intc_0>;
            interrupts = < 7 2 >;
            reg = < 0xf6000080 0x80 >;
            xlnx,family = "virtex5";
            xlnx,fifo-exist = <0x1>;
            xlnx,num-ss-bits = <0x2>;
            xlnx,num-transfer-bits = <0x8>;
            xlnx,sck-ratio = <0x20>;

            device@0 {
              compatible = "spidev";
              reg = <0>;  //Chip select 0
              spi-max-frequency = <3125000>;
            };
            device@1 {
              compatible = "spidev";
              reg = <1>;   //Chip select 1
              spi-max-frequency = <3125000>;
            };

} ;

 

 

 

3.- Linux doesn't understand directly the previous line compatible = "spidev", because it is related with the modalias property inside the spidev driver. That's why we need to add the "spidev" alias into <Linux git tree>/drivers/of/base.c, in the modalias_table, like it is shown below.

 

 

static struct of_modalias_table of_modalias_table[] = {
    { "fsl,mcu-mpc8349emitx", "mcu-mpc8349emitx" },
    { "mmc-spi-slot", "mmc_spi" },
    { "spidev", "spidev" },
};

 

 

 

4.- After that, we can compile the linux kernel and load it in the FPGA. In the linux start up sequency we will have the next output lines (this is an example with 4 SPI cores added in XPS):

 

xilinx-xps-spi f3000080.xps-spi: at 0xF3000080 mapped to 0xe1074080, irq=16
xilinx-xps-spi f1000000.xps-spi: at 0xF1000000 mapped to 0xe1078000, irq=17
xilinx-xps-spi f6000080.xps-spi: at 0xF6000080 mapped to 0xe107c080, irq=18
xilinx-xps-spi f2000000.xps-spi: at 0xF2000000 mapped to 0xe9082000, irq=19

 

 

5.- When in Linux, we need to create the spi device character files that will be located under the /dev/ directory. In this step we are going to use the mknod command, with the next syntax:

 

mknod  /dev/spidevA.B  c  <major number>  <minor number>

 

where A = bus number (refers to the SPI core), B = slave number, and c means a character device. The major number is the number assigned to the SPI driver, which can be found in the /proc/devices file, in the line that refers to the spi driver:

 

root:~> cat /proc/devices
Character devices:
  1 mem
  4 /dev/vc/0
  4 tty
  4 ttyS
  5 /dev/tty
  5 /dev/console
  5 /dev/ptmx
  7 vcs
 10 misc
 13 input
 90 mtd
128 ptm
136 pts
153 spi
204 ttyUL
254 miscelanea

Block devices:
  1 ramdisk
259 blkext
  7 loop
 31 mtdblock
 43 nbd

 

 

In our case, the major number is 153. To find the rest of the info needed, we first need to mount the sysfs filesystem. First of all, we need to create the /sys folder:

 

mkdir /sys

 

and then mount the sysfs filesystem using the next line:

 

mount  -t  sysfs  sysfs  /sys

 

Sysfs exports information about devices and drivers from the kernel device model to userspace, and is also used for configuration. We will be able to find the major and minor number for the spi cores under the /sys folder, like we are going to explain in the next lines.

 

All the SPI devices must be visible under the /sys/devices/plb.0/ folder. In our case we have:

 

 

root:/sys/devices/plb.0> ls -l
drwxr-xr-x    2 root     root            0 Jan  1 00:05 81800000.interrupt-controller
drwxr-xr-x    3 root     root            0 Jan  1 00:05 83e00000.serial
-r--r--r--          1 root     root     4096 Jan  1 00:05 devspec
drwxr-xr-x    4 root     root            0 Jan  1 00:05 f1000000.xps-spi
drwxr-xr-x    4 root     root            0 Jan  1 00:05 f2000000.xps-spi
drwxr-xr-x    2 root     root            0 Jan  1 00:05 f2010400.das
drwxr-xr-x    2 root     root            0 Jan  1 00:05 f2020400.miscelanea
drwxr-xr-x    2 root     root            0 Jan  1 00:05 f2040000.generador-signal
drwxr-xr-x    9 root     root            0 Jan  1 00:05 f3000080.xps-spi
drwxr-xr-x    5 root     root            0 Jan  1 00:05 f6000080.xps-spi
drwxr-xr-x    3 root     root            0 Jan  1 00:05 f8000000.flash
-r--r--r--          1 root     root     4096 Jan  1 00:05 modalias
-r--r--r--          1 root     root     4096 Jan  1 00:05 name
lrwxrwxrwx 1 root     root            0 Jan  1 00:05 subsystem -> ../../bus/of_platform
-rw-r--r--        1 root     root     4096 Jan  1 00:05 uevent
drwxr-xr-x    3 root     root            0 Jan  1 00:05 xps-ll-temac.1

 

Our spi devices' folders are f1000000.xps-spi, f2000000.xps-spi, f3000080.xps-spi and f6000080.xps-spi.

For example, under the f6000080.xps-spi. folder there is the following information:

 

root:/sys/devices/plb.0/f6000080.xps-spi> ls
devspec     modalias    spi32764.0   spi_master   uevent
driver          name           spi32764.1   subsystem

 

The folders spi32764.0 and spi32764.1 contain information about the two spi devices, the first one for the first slave and the second one for the second slave respectively. 32764 is the bus number = A, and 0 is the slave number (B), two of the pieces of information we need to execute the mknod command.

 

If we follow the previous folders more deeper we can found detailed information about each device. For example, under:

 

root:/sys/devices/plb.0/f6000080.xps-spi/spi32764.0/spidev/spidev32764.0> ls
dev        device     subsystem  uevent

In the dev file we can find both the major number and minor number assigned to the device:

 

root:/sys/devices/plb.0/f6000080.xps-spi/spi32764.0/spidev/spidev32764.0> cat dev
153:7

 

In this case, the major number is 153 (we already knew it) and the minor number is 7 (the last information we need for mknod). Therefore, in this case for the first slave the mknod command must be like it is shown below:

 

mknod  /dev/spidev32764.0  c  153  7

 

If we follow the same steps for the rest of the spi devices, we will have under /dev/ all the spi device character files (as many as spi slaves):

 

root:~> ls -l /dev/spi*
crw-r--r--    1 root     root     153,   9 Jan  1 00:28 /dev/spidev32763.0
crw-r--r--    1 root     root     153,   7 Jan  1 00:29 /dev/spidev32764.0
crw-r--r--    1 root     root     153,   8 Jan  1 00:29 /dev/spidev32764.1
crw-r--r--    1 root     root     153,   6 Jan  1 00:03 /dev/spidev32765.0
crw-r--r--    1 root     root     153,   0 Jan  1 00:29 /dev/spidev32766.0
crw-r--r--    1 root     root     153,   1 Jan  1 00:29 /dev/spidev32766.1
crw-r--r--    1 root     root     153,   2 Jan  1 00:29 /dev/spidev32766.2
crw-r--r--    1 root     root     153,   3 Jan  1 00:30 /dev/spidev32766.3
crw-r--r--    1 root     root     153,   4 Jan  1 00:30 /dev/spidev32766.4
crw-r--r--    1 root     root     153,   5 Jan  1 00:30 /dev/spidev32766.5

 

 

6.- We can now open the spi devices from userspace code in Linux using these files and the open() command. If we want to configure the spi device, we can use the ioctl() function, and if we want to read or write something, we can use both the read(), write() and ioctl() function as well. There is more information about the write/read procedure under the linux git tree:

 

<Linux git tree>/Documentation/spi/

 

folder, where there is an example on how to use the read, write and ioctl functions (spidev_test.c) and other useful info files.

 

7.- VERY IMPORTANT: If you need to use an SPI Core with more than 8 bits per transfer word (16 bits or 32 bits), you need to modify the xilinx spi drivers included with the linux distribution. That's because the xilinx_spi_of.c file is configured only for 8 bits. You can find this file in <LInux git tree>/drivers/spi/ .We had to change the line 75:

 

pdata->bits_per_word = 8;

 

with a way to read the bits per word from the dts file (where it is stablished in the parameter xlnx,num-transfer-bits = <0x8>; ) . Therefore, we have to replace the line 75 with the next code:

 

/* Bits per word */

 

bpword = of_get_property(ofdev->node, "xlnx,num-transfer-bits", &len);

printk("of_get_property devuelve bits per word: %d", *bpword);

 

if (!bpword || len < sizeof(*bpword))

{

         dev_warn(&ofdev->dev, "no 'xlnx,num-transfer-bits' property\n");

         return -EINVAL;

}

 

pdata->bits_per_word = *bpword;

 

 

The pointer bpword must be created previously:

 

const u32 *bpword;

 

 

8.- And that's all folks. If you have followed these steps you will have a properly working spi device.

 

 

 

Regards,

 

Borja

View solution in original post


All Replies
Scholar
Posts: 1,536
Registered: ‎09-10-2008

Re: How to use XPS SPI core driver in linux?

Hi,

 

I don't have answers to all the questions as I don't do my testing in the same manner that you need.

 

You can see what I do with an eeprom here.

 

http://xilinx.wikidot.com/osl-spi-driver

 

But notice that the spi bus number shows up under the sysfs file system.  I'm not sure what will show up when the spi-dev interface is used as I haven't done it, my apologies as I'd like to have an example there for you.

 

Have you read the docs in the kernel tree about spi-dev as that's where I'd start.  There's a test there and some documentation.

 

<kernel tree root>/Documentation\spi

 

I don't think I'd worry about using mdev in busybox as it just opens up other new tangents, just my opinion.  I have used it and it works, but has other learning to do.

 

Looks like there some other examples out on the web, not sure how good.

 

http://www.katix.org/spi003.html

 

Let me know if you make progress.

 

 

Contributor
Posts: 48
Registered: ‎07-08-2008

Re: How to use XPS SPI core driver in linux?

Hello John,

 

we think that we have the spi bus numbers that appear under sysfs (spi32763, spi32764, spi32765, spi32766) wich are symbolic links to other directories and appear under the directory /sys/bus/of_platform/drivers/spi_ppc4xx_of/.

 

We have read the documentation in <Linux tree>\Documentation\spi\, but we are not  sure about what is said about driver binding/unbinding, in the spidev documentation file:

 

DEVICE CREATION, DRIVER BINDING
===============================
The simplest way to arrange to use this driver is to just list it in the
spi_board_info for a device as the driver it should use:  the "modalias"
entry is "spidev", matching the name of the driver exposing this API.
Set up the other device characteristics (bits per word, SPI clocking,
chipselect polarity, etc) as usual, so you won't always need to override
them later.

(Sysfs also supports userspace driven binding/unbinding of drivers to
devices.  That mechanism might be supported here in the future.)

When you do that, the sysfs node for the SPI device will include a child
device node with a "dev" attribute that will be understood by udev or mdev.
(Larger systems will have "udev".  Smaller ones may configure "mdev" into
busybox; it's less featureful, but often enough.)  For a SPI device with
chipselect C on bus B, you should see:

    /dev/spidevB.C ... character special device, major number 153 with
    a dynamically chosen minor device number.  This is the node
    that userspace programs will open, created by "udev" or "mdev".

    /sys/devices/.../spiB.C ... as usual, the SPI device node will
    be a child of its SPI master controller.

    /sys/class/spidev/spidevB.C ... created when the "spidev" driver
    binds to that device.  (Directory or symlink, based on whether
    or not you enabled the "deprecated sysfs files" Kconfig option.)

Do not try to manage the /dev character device special file nodes by hand.
That's error prone, and you'd need to pay careful attention to system
security issues; udev/mdev should already be configured securely.

If you unbind the "spidev" driver from that device, those two "spidev" nodes
(in sysfs and in /dev) should automatically be removed (respectively by the
kernel and by udev/mdev).  You can unbind by removing the "spidev" driver
module, which will affect all devices using this driver.  You can also unbind
by having kernel code remove the SPI device, probably by removing the driver
for its SPI controller (so its spi_master vanishes).

Since this is a standard Linux device driver -- even though it just happens
to expose a low level API to userspace -- it can be associated with any number
of devices at a time.  Just provide one spi_board_info record for each such
SPI device, and you'll get a /dev device node for each device.

 

 

Under the /sys/bus/of_platform/drivers/xilinx-xps-spi/ directory there are 4 symbolic links and bind, uevent and unbind files:

 

bind

f2000000.xps-spi

f1000000.xps-spi

f3000080.xps-spi

f6000080.xps-spi

unbind

uevent

 

In the name of the 4 symbolic links (fxxxxxxxx.xps-spi), fxxxxxxxx is the direction of the device in the plb bus. Maybe we have to do the binding of the device and then mdev -s for the device appear in /dev/ directory?

 

We have been reading about driver binding/unbinding:

 

http://lwn.net/Articles/143397/

 

but we are not sure what the bus number should be and the exact name of the device.

 

Regards,

 

Borja

Contributor
Posts: 48
Registered: ‎07-08-2008

Re: How to use XPS SPI core driver in linux?

[ Edited ]

Hello,

 

maybe we are looking too deep for a way to talk to external devices using the XPS SPI cores in Embedded Linux. What would be the easiest way to achieve that?

 

We have recently found one example in the net where it is said that we have to add the "spi slave" devices in the dts, like it is shown below:

 

xps-spi@f3000080 {
#address-cells = ;
#size-cells = ;
cell-index = ;
compatible = "fsl,spi";
reg = ;
interrupts = ;

interrupt-parent = ;
/* provide chip-selects here */
gpios = &qe_pio_d 14 0>; /* CS1 */
mode = "cpu-qe";


device@0 {
compatible = "spidev";
reg = ; /* CS0*/
spi-max-frequency = ;
};


device@0 {
compatible = "spidev";
reg = ; /* CS1 */
spi-max-frequency = ;
};
};

 

It seems that defining each of the slaves used in the dts (based on the number of the slave select bits the XPS SPI core has), then linux should detect each of them and make a /dev/spidevB.C file for each one. What do you think?

Regards,

 

Borja

Scholar
Posts: 1,536
Registered: ‎09-10-2008

Re: How to use XPS SPI core driver in linux?

I think you were going too deep. You're new direction sounds very reaonable and matches what I did for the SPI eeprom.

 

let me know if you make progress as I'd like to document your hard work.

 

Thanks.

Contributor
Posts: 48
Registered: ‎07-08-2008

Re: How to use XPS SPI core driver in linux?

[ Edited ]

Hello John,

 

we have finally added the spi slaves into the dts using the structure we showed in the last message and linux has finally detected our spi devices. Now, if we look into sysfs we can find more directories and files related to slave devices. For each slave in a spi bus there are new files. One of them is the file dev. Making cat dev we found inside this file the major and minor number for each slave, for example:

 

root/: cat dev

153:7

 

We already knew that the major number for spi device driver was 153 (we saw it in /proc/devices), but we didn't know the minor number because previously the system didn't make the bind between the driver and each spi slave (and the minor number is generated dinamically). In spidev documentation it is clearly said not to make device nodes using mknod, but we haven't got mdev working, so our only option is mknod, using the sintax below as an example:

 

mknod /dev/spidev32764.0 c 153 7

 

32764 is the bus number of one of our spi devices and 0 the slave (it only has one slave). That bus number is referred to an XPS SPI core. If that bus number had more than one slave select line, the devices created by linux which are associated with them would be spidev32764.1, spidev32724.2, etc. (spidevA.B, where A=bus number and B=slave number). All of this is explained more or less in the spidev documentation in <linux tree>/Documentation/spi/.

 

After using mknod in that way, we have a node under /dev that can be opened from a user space program using open(file descriptor, ...). In the spidev.c code there is a structure called file_operations where are defined the functions this driver can use (for example, if we make an open from user space code program the function spi_init_device() (I have written this by memory since I don't have the code in front of me right now) is called by the driver. The same goes for write, read, close and ioctl system calls.

 

In <linux tree>/Documentation/spi/ there is a file called spidev_test.c where it is an example about how to use open, close and ioctl to transfer data using the XPS Spi device. We have started including these system calls in our user space program and we think that we have successfully managed to access one of ours XPS Spi device registers using ioctl, but we still need to do a lot of tests (they will have to wait until monday). We will let you know about the results.

 

However, I wonder if using xilinx_spi.c driver would be better than using spidev.c, because we have included both of them in the linux kernel compilation. In which level are all of them? (I mean, xilinx_spi.c uses spidev.c?). Where would be xilinx_spi.c used?

 

All suggestions will be thankful.

Scholar
Posts: 1,536
Registered: ‎09-10-2008

Re: How to use XPS SPI core driver in linux?

here's my thoughts, not necessary right.

 

The spi driver does not have a user space interface such that it can be used by another driver in the kernel or by the BSP in the kernel.

 

That's the whole point of the spi-dev interface, to allow you to use the SPI driver from user space. The spi-dev runs on top of the spi driver, similar to i2c in that regard.

 

The eeprom driver for spi is used rather than the spi-dev driver as it knows the details of SPI eeproms and it interfaces to the sysfs filesystem to allow userspace interaction.

 

We actually do use the dev interface of i2c to read the eeprom contents and this is similar to what you're trying to do. You can see that on the i2c driver page of the wiki.

 

You're making progress, hang in there, it takes diligence on some of this stuff, not all documented that well.

Contributor
Posts: 48
Registered: ‎07-08-2008

Re: How to use XPS SPI core driver in linux?

What do you think about xilinx_spi.c?

Scholar
Posts: 1,536
Registered: ‎09-10-2008

Re: How to use XPS SPI core driver in linux?

You have to use xilinx_spi.c if you want to talk to the Xilinx SPI Controller IP.

 

It's the layer next the h/w, spi-dev runs on top of it.

Contributor
Posts: 48
Registered: ‎07-08-2008

Re: How to use XPS SPI core driver in linux?

Hello Linn,

 

problem solved!! Following the steps I posted in the previous messages and generating device files using mknod, we have finally the XPS SPI core running. We have tested it with a program based on the spidev_test.c example.

 

During the start-up process, we had a problem with the interrupts of the SPI controllers, because they were added in the dts but not added in the bitstream to the interrupt controller. We have tested a 8 bits XPS SPI Core from Linux and everything is ok. Now, we have to test another three SPI cores, each of them with different configuration.

 

We will let you know when everything works perfectly.

 

If you need more info for documentation purposes, I can make a detailed step-by-step procedure to help other people in the (near) future.

 

Regards,

 

Borja